前言:html
shiro由於其簡單、可靠、實現方便而成爲如今最經常使用的安全框架,那麼這篇文章除了會用簡潔明瞭的方式講一下基於spring的shiro詳細配置和登陸註銷功能使用以外,也會根據慣例在文章最後總結一下shiro的大體配置使用流程,但願本篇文章可以給你們一種原來shiro是這麼簡單的錯覺感受。java
注意:該篇文章的開始是創建在一個完備的spring+mybatis的開發環境中,除了shiro以外的配置基本不會涉及到。作好本身--eguid原創文章web
shiro補充以及shiro註解問題解決文章(但願對你們有用):shiro與spring整合詳解與spring項目中shiro註解不生效的解決辦法spring
本篇文章使用shiro-1.4.0版本apache
一、shiro官方下載地址:http://shiro.apache.org/download.html數組
二、maven依賴項:安全
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
<!-- shiro過濾器 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意事項:spring在加載上下文的時候,是沒有掃描註解的,因爲咱們在自定義的realm中用到了spring的註解,因此須要在shiro的自定義realm以前進行註解掃描。session
<context:component-scan base-package="cc.eguid" />mybatis
<!-- shiro的生命週期處理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 使用shiro安全檢查註解 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> <!-- 自定義的安全數據源,用來實現自定義的登陸驗證、角色驗證、權限驗證 --> <bean id="myRealm" class="cc.eguid.shiro.MyRealm"/> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> </bean> <!-- shiro過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 配置安全管理器 --> <property name="securityManager" ref="securityManager" /> <!-- 身份認證失敗跳轉的地址,沒有登陸固然就跳轉到登陸地址 --> <property name="loginUrl" value="/login/" /> <!-- 身份認證成功跳轉的地址,通常登陸成功後會跳轉到系統首頁 --> <property name="successUrl" value="/" /> <!-- 權限認證失敗跳轉的地址 ,用來提示當前用戶沒有操做權限,能夠不須要--> <property name="unauthorizedUrl" value="/login/unauthorized" /> <property name="filterChainDefinitions"> <!--anon 表示匿名訪問,不須要認證以及受權 --> <!--authc表示須要認證 沒有進行身份認證是不能進行訪問的 --> <!--authc,roles[admin]表示是admin角色的用戶才能訪問 --> <value> /* = authc /static/** =anon /login/** = anon /admin/** = authc,roles[admin] /camera/** = authc /** = authc </value> </property> </bean>
過濾器裏能夠配置註釋裏寫的很清楚,anon表示匿名訪問,authc表示須要進行登陸驗證、權限驗證、角色驗證app
自定義realm實現請看下面。
public class MyRealm extends AuthorizingRealm{ Logger log=Logger.getLogger(MyRealm.class); @Autowired private UserService userService;//這是本身實現的用戶信息操做類,實現用戶信息,用戶角色信息、用戶權限信息查詢功能 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { log.info("從登陸憑證中獲取用戶信息,因爲咱們在doGetAuthenticationInfo中直接在principals中存放的用戶信息對象,因此咱們能夠得到當前用戶信息"); UserInfo user = (UserInfo) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 查詢角色信息 Collection<String> roles = userService.findRoles(user); log.info("查詢用戶角色信息並添加到shiro權限驗證器中,一個用戶能夠對應多個角色"); info.addRoles(roles); // 查詢權限信息 Collection<String> permissions = userService.findPermissions(user); log.info("把用戶權限信息添加到shiro權限過濾器中"); info.addStringPermissions(permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{ log.info("shiro登陸驗證"); // 在咱們本身的登陸流程中應該確保登陸的用戶信息已經插入AuthenticationToken中,這樣才能經過shiro的認證流程 String loginname= token.getPrincipal().toString(); //雖然在登陸流程中咱們給的是String的面,可是shiro中已經寫死了密碼是個字符數組,因此老老實實的把密碼轉成char[]吧 char[] password=(char[]) token.getCredentials(); // 查詢用戶名對應的用戶信息 UserInfo user =userService.queryUserInfoByLoginName(loginname); log.info("驗證用戶信息:"+loginname+","+user+"密碼:"+password); if (user != null&&user.getPassword()!=null) { //直接把用戶信息對象和密碼塞進shiro驗證器,shiro會自動判斷密碼是否正確 AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, password, getName()); return authenticationInfo; } return null; }
3、shiro登陸和註銷流程實現
/** * shiro註銷,shiro會自動把session釋放,因此不須要調用session.invalidate();方法 */ @Override public void logout(){ Subject currentUser = SecurityUtils.getSubject(); currentUser.logout(); } /** * shiro登陸 */ @Override public boolean singin(UserInfo user){ try{ Subject subject = SecurityUtils.getSubject() ; UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginusername(),user.getPassword()) ; subject.login(token); log.info("shiro登陸驗證成功"); return true; }catch(AuthenticationException e){ log.error("shiro登陸驗證不經過",e); return false; } } /** * 判斷用戶是否登陸(shiro方式) */ @Override public boolean isSignon() { Subject subject = SecurityUtils.getSubject() ; return subject.isAuthenticated(); }
/** * 從shiro中獲取當前登陸的用戶信息 */ @Override public UserInfo getCurrentUserInfo(){ Subject subject = SecurityUtils.getSubject() ; return (UserInfo) subject.getPrincipal(); }
以上,但願對你們有所幫助。-- 作好本身--eguid