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();
}


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