spring整合shiro

 

配置一个存储权限的缓存  ehcache-shiro.xml

<ehcache updateCheck="false" name="shiroCache">

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />
</ehcache>

 

整合spring配置  applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"   
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans.xsd    
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop.xsd    
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx.xsd    
    http://www.springframework.org/schema/context    
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    <description>Shiro的配置</description>
    
    <!-- SecurityManager配置 -->
    <!-- 配置Realm域 -->
    <!-- 密码比较器 -->
    <!-- 代理如何生成? 用工厂来生成Shiro的相关过滤器-->
    <!-- 配置缓存:ehcache缓存 -->
    <!-- 安全管理 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="realm" ref="authRealm"/><!-- 引用自定义的realm -->
        <!-- 二级缓存 -->
        <property name="cacheManager" ref="shiroEhcacheManager"/>
    </bean>

    <!-- 自定义权限认证 -->
    <bean id="authRealm" class="com.xwer.jk.shiro.AuthorRealm">
        <property name="userService" ref="userService"/>
        <!-- 自定义密码加密算法   密码比较器 -->
        <property name="credentialsMatcher" ref="passwordMatcher"/>
    </bean>
    
    <!-- 设置密码加密策略自定义的密码比较器  md5hash -->
    <bean id="passwordMatcher" class="com.xwer.jk.shiro.CustomerCrednetialsMatcher"/>

    <!-- filter-name这个名字的值来自于web.xml中filter的名字 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录页面  -->
        <property name="loginUrl" value="/index.jsp"></property>
        <!-- 登录成功后 -->      
        <property name="successUrl" value="/home.action"></property>
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤 -->
            <value>
                /index.jsp* = anon
                /home* = anon
                /sysadmin/login/login.jsp* = anon
                /sysadmin/login/logout.jsp* = anon
                /login* = anon
                /logout* = anon
                /components/** = anon
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /make/** = anon
                /skin/** = anon
                /stat/** = anon
                /ufiles/** = anon
                /validator/** = anon
                /resource/** = anon
                /** = authc
                /*.* = authc
            </value>
        </property>
    </bean>

    <!-- 用户授权/认证信息Cache, 采用EhCache缓存  下面不用多配置 -->
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean>

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 生成代理,通过代理进行控制 -->
    <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>
    
</beans>

 

 

自定义比较器类

 

/**
 * 自定义密码比较器
 * @author Administrator
 *
 */
public class CustomerCrednetialsMatcher extends SimpleCredentialsMatcher{

    //重写父类方法, token 表示用户在页面输入的用户名和密码,info  表示从数据库取出的数据
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //1.向下转型
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        
        //2.将用户 在界面输入的原始加密 进行md5 hash加密   -------  直接使用toString 获取的是char[] 的地址
        //String pwd = Encrypt.md5(upToken.getPassword().toString(), upToken.getUsername());
        String pwd = Encrypt.md5(new String(upToken.getPassword()), upToken.getUsername());
        
        //3.从数据库取出加密的密码
        Object dbPwd = info.getCredentials();
        return this.equals(pwd, dbPwd);
    }
}


Encrypt 类

public class Encrypt {
    /*
     * 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,
     * 常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,
     * 产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,
     * 可以到一些md5解密网站很容易的通过散列值得到密码“admin”,
     * 即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,
     * 如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。
     */
    
    //高强度加密算法,不可逆
    /**
     * 默认加密方式
     * @param password  用户密码
     * @param salt  用户名
     * @return
     */
    public static String md5(String password, String salt){
        return new Md5Hash(password,salt,2).toString();
    }
    
    public static void main(String[] args) {
        System.out.println(new Md5Hash("admin","admin",2).toString());
    }
    
    
}

 

 

 

shiro 核心认证授权 AuthorRealm.java

public class AuthorRealm  extends AuthorizingRealm{
    private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    private UserService userService;
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    
    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取当前用户,先根据realm的名字去获取相应的realm
        User user = (User)principals.fromRealm(this.getName()).iterator().next();
        logger.info("用户 {} 授权中.....",user.getUserName());
        //得到权限字符串
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取用户的权限
        Set<Role> roles = user.getRoles();//对象导航,关联级别数据加载,得到当前用户的所有角色    
        List<String> list = new ArrayList<String>();
        for(Role role :roles){
            //对象导航,关联级别数据加载,得到每个角色下的模块列表
            Set<Module> modules = role.getModules();
            for(Module m:modules){
                if(m.getCtype()==0){
                    //说明是主菜单,组织权限字符串
                    list.add(m.getCpermission());
                }
            }
        }

        info.addStringPermissions(list);
        return info;
    }
    //认证  登录
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken)token;
        
        logger.info("用户 {} 认证中.....",new String(upToken.getUsername()));
        
        //
        String hql = "from User where userName = ?";
        //User user = userService.findUserByName(upToken.getUsername());
        List<User> list = userService.find(hql, User.class, new String[]{upToken.getUsername()});
        
        if(list!=null&& list.size()>0){
        User user = list.get(0);
            //当前用户,用户密码
            AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
            return info;  //此处如果返回,就会立即 进入密码比较器    
        }
        return  null;
    }
}

 

posted @ 2017-09-13 00:06  xwer  阅读(241)  评论(0编辑  收藏  举报