Shiro的配置與使用

shiro的介紹

shiroapache提供的強大而靈活的開源安全框架,它主要用來處理身份認證,授權,企業會話管理和加密。靈活性強,易學易擴展

1、環境配置maven

 

<dependency>
	       <groupId>org.apache.shiro</groupId>
	       <artifactId>shiro-core</artifactId>
	       <version>1.3.2</version>  
        </dependency>  
       <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-web</artifactId>  
            <version>1.3.2</version>  
       </dependency>  
       <dependency>  
           <groupId>org.apache.shiro</groupId>  
           <artifactId>shiro-spring</artifactId>  
           <version>1.3.2</version>  
        </dependency> 
		<dependency>
           <groupId>org.apache.shiro</groupId>
           <artifactId>shiro-ehcache</artifactId>
           <version>1.3.2</version>
         </dependency>
 <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>
         <dependency>
         <groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>2.2.2</version>
   </dependency>


Spring配置 

 

	<!-- 配置進行授權和認證的 Realm -->


	<bean id="myRealm"
		class="com.yonyou.nccloud.gwm.shrio.realm.MyRealm"></bean>


	<!-- 配置 Shiro 的 SecurityManager Bean. -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
       <property name="cacheManager" ref="shcacheManager"/>
    <!--     <property name="rememberMeManager" ref="rememberMeManager" /> -->
        <property name="realm" ref="myRealm"/>
    </bean>
    
    <!-- 配置 Bean 後置處理器: 會自動的調用和 Spring 整合後各個組件的生命週期方法. -->
	<bean id="lifecycleBeanPostProcessor" 
		class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
		
   
    <!-- 配置 ShiroFilter bean: 該 bean 的 id 必須和 web.xml 文件中配置的 shiro filter 的 name 一致  -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    	<!-- 裝配 securityManager -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 配置登陸頁面 -->
         <property name="loginUrl" value="/mygwapp/login"/> 
        <!-- 登陸成功後的一面 -->
      <!-- <property name="successUrl" value="/AdminIndexController/index.htm"/> -->
     <!--   <property name="unauthorizedUrl" value="/404.jsp"/>  -->
		<!-- 具體配置需要攔截哪些 URL, 以及訪問對應的 URL 時使用 Shiro 的什麼 Filter 進行攔截.  -->
        <property name="filterChainDefinitions">
            <value>
            	<!-- 配置登出: 使用 logout 過濾器                    /**=anon-->
                  /**=authc
                  /mygwapp/logout=logout
            </value>
        </property>
    </bean>
 

SpringMvc.xml

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true" />
     </bean>

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
    <bean  class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
    <property name="exceptionMappings">  
        <props>  
            <prop key="org.apache.shiro.authz.UnauthorizedException">  
               /403
            </prop>  
            <prop key="org.apache.shiro.authz.UnauthenticatedException">  
                /403
            </prop>  
        </props>  
    </property>  
</bean>  
	

web.xml

<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>

到此環境已OK 不懂得地方 自行百度

首先說

2、認證操作

在登錄的controller中,登錄成功後

                       Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(username, password);
subject.login(token);

執行subject.login後會調用myRealm類中的方法doGetAuthenticationInfo

MyRealm

public class MyRealm extends AuthorizingRealm {

	@Autowired
	private ITenantAuthrityService tenantAuthrityService;
	
	/**
	 * 
	 * 實現思路: 1)
	 * 授權方法: 1. 實際返回的是 SimpleAuthorizationInfo 類的實例 2. 可以調用
	 * SimpleAuthorizationInfo 的 addRole 來添加當前登錄 user 的權限信息. 3. 可以調用
	 * PrincipalCollection 參數的 getPrimaryPrincipal() 方法來獲取用戶信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principalCollection) {
		    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
			List<String> permissions = new ArrayList<String>();
			String username = (String) principalCollection
					.getPrimaryPrincipal();
		    List<String> mms= tenantAuthrityService.getMyPermissions(username);
		    permissions.addAll(mms);
		    permissions.add("/main/test1");
			permissions.add("/main/test");
			simpleAuthorizationInfo.addStringPermissions(permissions);
            return simpleAuthorizationInfo;
	}

	/**
	 * 
	 *  Subject currentUser = SecurityUtils.getSubject();
	 * UsernamePasswordToken token = new UsernamePasswordToken(username,
	 * password); currentUser.login(token); 3. 當 Subject 調用 login 方法時, 即會觸發當前的
	 * doGetAuthenticationInfo 方法x
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		String username = (String) token.getPrincipal();
        String source = generateSalt();
		ByteSource credentialsSalt = new Md5Hash(source);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
        		username,new String("abcd").toCharArray(),
				credentialsSalt, getName());
		return info;
	}
    

	
	
	private String generateSalt() {
		SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
		String hex = secureRandom.nextBytes(3).toHex(); // 一個Byte佔兩個字節,此處生成的3字節,字符串長度爲6
		return hex;
	}

	@PostConstruct
	public void setCredentialMatcher() {

		setCredentialsMatcher(new SimpleCredentialsMatcher());

	}
	 //重寫權限判斷方法,加入正則判斷
   @Override
    public boolean isPermitted(PrincipalCollection principals, String permission) {
	    AuthorizationInfo info = getAuthorizationInfo(principals);
        Collection<String> permissions = info.getStringPermissions();
        return permissions.contains(permission) || patternMatch(permissions, permission);
    }

    /**
     * 正則
     * @param patternUrlList
     * @param requestUri
     * @return
     */
    public boolean patternMatch(Collection<String> patternUrlList, String requestUri) {
        boolean flag = false;
        for (String patternUri : patternUrlList) {
            if (StringUtils.isNotEmpty(patternUri)) {
            	System.out.println(requestUri+"========"+patternUri);
                Pattern pattern = Pattern.compile(patternUri);
                Matcher matcher = pattern.matcher(requestUri);
                if (matcher.matches()) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }
}

我們在doGetAuthenticationInfo方法中去

SimpleAuthenticationInfo中放入賬號及密碼

在shrio內部會比較 SimpleAuthenticationInfo對象與之前subject 的UsernamePasswordToken 的賬號密碼進行比對

如果一致則認證成功

3、授權操作

當我們在controller的方法上添加@RequiresPermissions(value={"/main/test1"})

這時就會進行授權操作 調用MyRealm的doGetAuthorizationInfo方法

在該方法中將可以訪問的路徑存放在simpleAuthorizationInfo中,返回它的對象

然後調用isPermitted方法

在該方法中我們對註解上的value和info中的權限集合 進行正則匹配

如果匹配成功,則返回true,不成功返回false,

授權完畢

4、銷燬認證信息

Subject subject=SecurityUtils.getSubject();
if(subject.isAuthenticated()){
//將session註銷
subject.logout();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章