前言:
shiro因為其簡單、可靠、實現方便而成為現在最常用的安全框架,那么這篇文章除了會用簡潔明了的方式講一下基於spring的shiro詳細配置和登錄注銷功能使用之外,也會根據慣例在文章最后總結一下shiro的大致配置使用流程,希望本篇文章能夠后能給大家一種原來shiro這么簡單的錯覺感覺。
注意:該篇文章的開始是建立在一個完備的spring+mybatis的開發環境中,除了shiro之外的配置基本不會涉及到。做好自己--eguid原創文章
一、依賴的jar包
本篇文章使用shiro-1.4.0版本
1、shiro官方下載地址:http://shiro.apache.org/download.html
2、maven依賴項:
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring</artifactId>
- <version>1.4.0</version>
- </dependency>
為什么maven只需要shiro-spring這個依賴項就行了,因為shiro-spring依賴shiro-core和shiro-web兩個包,所以會自動繼承shiro-core和shiro-web以及這兩個包所依賴的項。
二、基於spring的配置方式
1、配置shiro過濾器
- <!-- 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>
2、基於spring的shiro配置
注意事項:spring在加載上下文的時候,是沒有掃描注解的,由於我們在自定義的realm中用到了spring的注解,所以需要在shiro的自定義realm之前進行注解掃描。
<context:component-scan base-package="cc.eguid" />
(1)spring下的shiro完整配置
- <!-- 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>
這段配置需要修改的只有shiro過濾器和shiro安全數據源(realm)。
過濾器里可以配置注釋里寫的很清楚,anon表示匿名訪問,authc表示需要進行登錄驗證、權限驗證、角色驗證
自定義realm實現請看下面。
(2)自定義的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;
- }
三、shiro登錄和注銷流程實現
- /**
- * shiro注銷,shiro會自動把session釋放,所以不需要調用session.invalidate();方法
- */
- @Override
- public void logout(){
- Subject currentUser = SecurityUtils.getSubject();
- <span style="white-space:pre"> </span>currentUser.logout();
- }
- /**
- * shiro登錄
- */
- @Override
- public boolean singin(UserInfo user){
- try{
- Subject subject = SecurityUtils.getSubject() ;
- <span style="white-space:pre"> </span>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配置使用總結
1、在web.xml中配置shiro的過濾器
2、在spring應用上下文(例如:applicationContext.xml)中配置shiro過濾器及自定義realm等其他輔助配置,其中
shiro過濾器可以配置哪些接口需要進行登錄驗證、角色驗證、權限驗證,哪些不需要進行驗證,自定義realm則是為shiro驗證器提供了用戶信息、用戶角色信息和用戶權限信息等數據源,進而讓shiro進行三項驗證。
3、shiro提供了完整的登錄流程和注銷流程,對原有登錄和注銷流程做一定修改是免不了的。
以上,希望對大家有所幫助。-- 做好自己--eguid