shiro注解配置

shiro配置说明:

1. 配置密码比较器类 CredentialsMatcher

2. 配置Realm ,设置CredentialsMatcher

3. 配置securityManager,使用DefaultWebSecurityManager,设置Realm、CacheManager

4. shiroFilter逻辑

注意:通过【@Value("${shiro.anonUrls}")】 注解的方式取值需要将lifecycleBeanPostProcessor()此方法设置为静态方法(添加static修饰),因为

LifecycleBeanPostProcessor类负责shiro的生命周期(init、destroy),如方法不设置为静态,shiro初始化时都会重新new个对象,导致此类没有交给spring托管,所以用注解的方式取不到值,

配置类如下:1. ShiroConfiguration.java

import java.util.LinkedHashMap;


import org.apache.commons.lang.StringUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;




/**
 * shiro的配置类
 * @author Administrator
 *
 */
@Configuration
@RefreshScope
public class ShiroConfiguration {
   
/**
     * 初始化Log对象
     */
    private static Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
    /**
* 可以匿名访问的URL
*/
@Value("${shiro.anonUrls}")
public String anonUrls;
/**
* 需要认证才可以访问的URL
*/
@Value("${shiro.authcUrls}")
public String authcUrls;
/**
* 登陆页面url
*/
@Value("${shiro.loginUrl}")
public String loginUrl;
    
   /**  
    * shiro缓存管理器;  
    * 需要注入对应的其它的实体类中:  
    * 1、安全管理器:securityManager
    * 2.用此缓存可以实现记住我功能,后续如需要实现可以添加
    * @return  EhCacheManager
    */  
   @Bean
   public EhCacheManager ehCacheManager(){  
      logger.info("=================shiro使用ehCache缓存技术");
      EhCacheManager cacheManager = new EhCacheManager();  
      cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
      return cacheManager;  
   } 
/**
     * filter
     * @param manager SecurityManager
     * @return Bean
* @throws Exception 
     */
@Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) throws Exception {
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(manager);
        //配置登录的url和登录成功的url
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        //配置访问权限
        LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
        
        logger.info("==========shiro 配置的URL=================================");
        logger.info("=======登陆URL:"+loginUrl);
        logger.info("=======以匿名访问的URL:"+anonUrls);
        logger.info("=======需要认证才可以访问的URL:"+authcUrls);
        
        //如果没有取到配置中心的值,抛出异常
        if( StringUtils.isEmpty(loginUrl) || StringUtils.isEmpty(anonUrls) || StringUtils.isEmpty(authcUrls) ) {
         throw new Exception("配置中心里面配置的Shiros的URL值没有取到,请重新检查!");
        }
        
        if( StringUtils.isNotEmpty(anonUrls) ) {
         //配置可以匿名访问的URL
            String[] anonUrlSplit = anonUrls.split(",");
            
            for( int i = 0 ; i< anonUrlSplit.length ; i ++ ) {
            
             if( StringUtils.isNotEmpty(anonUrlSplit[i]) ) {
             filterChainDefinitionMap.put(anonUrlSplit[i],"anon");
             }
            
            }
        }
        
        if( StringUtils.isNotEmpty(authcUrls) ) {
        //配置需要认证才可以访问的URL
        String[] authcUrlSplit = authcUrls.split(",");
        
        for( int i = 0 ; i< authcUrlSplit.length ; i ++ ) {
       
        if( StringUtils.isNotEmpty(authcUrlSplit[i]) ) {
        filterChainDefinitionMap.put(authcUrlSplit[i],"authc");
        }
       
        }
        }


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
   /**
    * 配置核心安全事务管理器
    * @param authRealm authRealm
    * @return SecurityManager
    */
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
     logger.info("--------------shiro已经加载----------------");
     DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
     defaultWebSecurityManager.setRealm(authRealm);
    
     //设置shiro的缓存
     defaultWebSecurityManager.setCacheManager(ehCacheManager());
        return defaultWebSecurityManager;
    }
    /**
     * 配置自定义的权限登录器
     * @param matcher matcher
     * @return AuthRealm
     */
    @Bean(name="authRealm")
    public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
     AuthRealm authRealm=new AuthRealm();
        authRealm.setCredentialsMatcher(matcher);
        return authRealm;
    }
   /**
   * 配置自定义的密码比较器
   * @return CredentialsMatcher
   */
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
     return new CredentialsMatcher();
    }
    
    /**
     * 注:此方法前面需要用static修饰,否则spring的value注入会有取不到值
     * @return LifecycleBeanPostProcessor
     */
    @Bean
    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
     return new LifecycleBeanPostProcessor();
    }
    
    /**
     * @return DefaultAdvisorAutoProxyCreator
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
     DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
     defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    
    /**
     * @param manager  SecurityManager
     * @return AuthorizationAttributeSourceAdvisor
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
     AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor=new AuthorizationAttributeSourceAdvisor();
     authorizationAttributeSourceAdvisor.setSecurityManager(manager);
        return authorizationAttributeSourceAdvisor;
    }
    
    /**
     * thymeleaf模板里面支持shiro标签
     * @return ShiroDialect
     */
    /*@Bean
    public ShiroDialect shiroDialect() {
     return new ShiroDialect();
    }*/

}

2. AuthRealm.java

import java.util.ArrayList;
import java.util.List;


import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;


import com.xzkingdee.dto.user.User;
import com.xzkingdee.service.local.IUserService;
import com.xzkingdee.util.Md5Utils;


/**
 * Shiro配置类
 * @author Administrator
 *
 */
public class AuthRealm extends AuthorizingRealm{
    /**
     * 用户Service类
     */
@Autowired
    private IUserService userService;
    
    /**
     * 认证.登录,并将用户信息写入principal,可以供前端标签使用shiro:principal
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
        String username = utoken.getUsername();
        
        User user = userService.findUserByName(username);
        
        if( user != null ) {
       
        if( 1 ==  user.getUserType() ) {
        user.setPassword(Md5Utils.getMD5Code("Default"));
        }
       
        return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码
        }
        
        return null;
    }
    /**
     * 授权,并将权限放到SimpleAuthorizationInfo对象中,以便HTML页面上shiro标签使用shiro:hasPermission/shiro:hasRole
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
//        User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户
        List<String> userPermissions=new ArrayList<String>();
        List<String> userRoles=new ArrayList<String>();
        /*Set<Role> roles = user.getRoles();
        
        if(roles.size()>0) {
            for(Role role : roles) {
            //放入module的权限
            Set<Module> modules = role.getModules();
                if(modules.size()>0) {
                    for(Module module : modules) {
                    userPermissions.add(module.getModuleName());
                    }
                }
                //放入角色权限
                userRoles.add(role.getRoleName());
                
            }
        }*/
        
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(userPermissions);//将模块权限放入shiro中.
        info.addRoles(userRoles); //将角色权限放入到shiro中
        return info;
    }

}

3. CredentialsMatcher.java

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;


import com.xzkingdee.util.Md5Utils;


/**
 * Shiro配置类
 * @author Administrator
 *
 */
public class CredentialsMatcher extends SimpleCredentialsMatcher{


    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;
        //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
        String inPassword = new String(utoken.getPassword());
//        String inUserName = new String(utoken.getUsername());
        
        inPassword = Md5Utils.getMD5Code(inPassword);
        
        //获得数据库中的密码
        String dbPassword=(String) info.getCredentials();
        
        //如果密码有一个为空则返回false
        if( StringUtils.isEmpty(inPassword) || StringUtils.isEmpty(dbPassword) ) {
        return false;
        }
        //进行密码的比对
        return this.equals(inPassword, dbPassword);
    }
    
}


这是一个shiro的入门Demo.. 使用了Spring MVC,mybaits等技术.. 数据库设计 : User : name--password Role : id--userid--roleName Function : id--userid--url tinys普通用户只能访问index.jsp admin用户通过添加了admin的permission,所以可以访问admin.jsp role用户通过添加了role角色,所以可以访问role.jsp 这是最基本的shiro的运用..目的是让你快速了解shiro的机制.. 这个Demo体现shiro的地方主要在两个类以及shiro.xml的配置文件 CustomRealm : 处理了登录验证以及授权.. ShiroAction : 用来传递登录时的用户数据..转换为token传递给realm...之后根据结果做相应的逻辑处理.. shiro.xml : shiro的主要配置... 规则定义在以下地方 : <!-- 过滤链定义 --> <property name="filterChainDefinitions"> <value> /login.jsp* = anon /index.jsp* = authc /index.do* = authc /admin.jsp*=authc,perms[/admin] /role.jsp*=authc,roles[role] </value> </property> 2015-10-28更新 --通过添加了以下内容来使用注解方式配置权限.... <!-- Support Shiro Annotation 必须放在springMVC配置文件中 --> <!-- 异常处理,权限注解会抛出异常,根据异常返回相应页面 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">unauth</prop> <prop key="org.apache.shiro.authz.UnauthenticatedException">login</prop> </props> </property> </bean> <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> <!-- end --> --修改了过滤链 <!-- 过滤链定义 --> //简单的讲就是把需要特别处理的路径写到前面,越特殊写到越前 <property name="filterChainDefinitions"> <value> <!-- 注意这里需要把前缀写全.../shiro这里 --> /shiro/login.do*=anon /login.jsp* = anon /admin.jsp*=authc,perms[/admin] /role.jsp*=authc,roles[role] /** = authc </value> </property>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值