shiro整合spring
来源:互联网 发布:java中常用io流类 编辑:程序博客网 时间:2024/05/21 19:29
本文是对CSDN开涛大神的shiro教程第十二章——shiro整合spring的一个整理。
Shiro是最近非常流行的安全框架,比spring security要简单一些,轻量一些。但其功能相当强大,不仅提供权限管理、还集成了单点登录、分布式session等等。
下面是shiro和spring的整合流程。
一般来说权限管理系统可以设计5张表,user表,role表,permission表,他们两两之间分别是一对多的关系,即一个用户可以拥有多个角色,一个角色可以拥有多个权限。因此还需建立user_role_relation表和role_permission
表。
SSM整合shiro首先把这五张表的dao层写好。用户量较小时,可以使用spring JDBCTemplate写dao层。
shiro提供了SimpleHash,他是一个加密工具,使用起来非常方便。
private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); private String algorithmName = "md5"; private int hashIterations = 2; public void encryptPassword(User user) { user.setSalt(randomNumberGenerator.nextBytes().toHex());/*shiro提供的simpleHash,分别赋值加密算法、密码、盐、加密循环次数。并转为16进制返回。 */ String newPassword = new SimpleHash( algorithmName, user.getPassword(), //CredentialsSalt在实体类中由username+salt构成 ByteSource.Util.bytes(user.getCredentialsSalt()), hashIterations).toHex(); user.setPassword(newPassword); }
SimpleHash构造函数里有五个参数,分别是算法名称(这里使用的MD5),加密数据,盐,加密循环次数。这样我们在service层插入用户时,就可以使用这个encryptPassword方法将用户密码加密后插入DB了。至于service层无非也是调用dao做一些CURD的操作,不做一一阐述了。重点是下面的Realm
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { /** *@Author hfismyangel@163.com *@Description: * 保存登陆成功后的信息 *@Date: 8:46 2017/8/18 * @param principals */ String username = (String)principals.getPrimaryPrincipal(); //简单授权信息,保存用户登录状态 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(userService.findRoles(username)); authorizationInfo.setStringPermissions(userService.findPermissions(username)); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /** *@Author hfismyangel@163.com *@Description: * 验证是否能登录 *@Date: 8:47 2017/8/18 * @param token */ //直接从token里拿用户名 String username = (String)token.getPrincipal(); User user = userService.findByUsername(username); if(user == null) { throw new UnknownAccountException();//没找到帐号 } if(Boolean.TRUE.equals(user.getLocked())) { throw new LockedAccountException(); //帐号锁定 } //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user.getUsername(), //用户名 user.getPassword(), //密码 ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt getName() //realm name ); return authenticationInfo; }
这个Realm可以理解为对于是否登录/拥有权限做逻辑判断的一层。首先自定义一个类,继承Shiro的AuthorizingRealm父类。重写doGetAuthorizationInfo和doGetAuthenticationInfo方法即可,注意两个方法互为重载方法。一个是用于保存登陆成功后的信息,一个是用于判断是否登录。
注意第二个doGetAuthorizationInfo方法里调用的token.getPrincipal()方法,是直接从token中拿到用户名,而第一个doGetAuthorizationInfo方法里token.getPrincipal()是从PrincipalCollection通过遍历器拿到第一个用户名,PrincipalCollection 是个身份集合,保存各种身份信息,具体实现可以看源码。
最简单的代码配置就到此为止,再配置一下spring-shiro.xml的配置文件,在web.xml里配置一个shiro的过滤器就可以进行测试了。
下面是shiro与srpring整合的配置文件,原文注释写的比较清晰,不作解释了。另外最好根据这个shiro流程图来理解。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!--dao层、passwordHelper类、与shiro-web无关--> <!-- 缓存管理器 使用Ehcache实现 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean> <!-- 凭证匹配器 ,用于管理密码重试次数--> <bean id="credentialsMatcher" class="com.github.zhangkaitao.shiro.chapter12.credentials.RetryLimitHashedCredentialsMatcher"> <constructor-arg ref="cacheManager"/> <property name="hashAlgorithmName" value="md5"/> <property name="hashIterations" value="2"/> <property name="storedCredentialsHexEncoded" value="true"/> </bean> <!-- Realm实现,包含两部分AuthenticationToken和AuthenticationInfo--> <bean id="userRealm" class="com.github.zhangkaitao.shiro.chapter12.realm.UserRealm"> <property name="userService" ref="userService"/> <property name="credentialsMatcher" ref="credentialsMatcher"/> <property name="cachingEnabled" value="true"/> <property name="authenticationCachingEnabled" value="true"/> <property name="authenticationCacheName" value="authenticationCache"/> <property name="authorizationCachingEnabled" value="true"/> <property name="authorizationCacheName" value="authorizationCache"/> </bean> <!-- 会话ID生成器,指定使用uuid生成--> <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/> <!-- 会话Cookie模板 --> <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="sid"/> <property name="httpOnly" value="true"/> <property name="maxAge" value="180000"/> </bean> <!-- 会话DAO,管理session。 shiro的session都是存在缓存中的,所有会有一个sessionDAO的类EnterpriseCacheSessionDAO来做CRUD操作--> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/> <property name="sessionIdGenerator" ref="sessionIdGenerator"/> </bean> <!-- 会话验证调度器 --> <!--shiro提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话;出于性能考虑, 一般情况下都是获取会话时来验证会话是否过期并停止会话的;但是如在web环境中,如果用户不主动退出是不知道会话是否过期的, 因此需要定期的检测会话是否过期,Shiro提供了会话验证调度器SessionValidationScheduler。--> <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> <!--设置调度时间间隔,单位毫秒,默认是1小时--> <property name="sessionValidationInterval" value="1800000"/> <property name="sessionManager" ref="sessionManager"/> </bean> <!--==============================================================================================================--> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="1800000"/> <property name="deleteInvalidSessions" value="true"/> <property name="sessionValidationSchedulerEnabled" value="true"/> <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/> <property name="sessionDAO" ref="sessionDAO"/> <property name="sessionIdCookieEnabled" value="true"/> <!--存储sessionID的jsessionId--> <property name="sessionIdCookie" ref="sessionIdCookie"/> </bean> <!-- 安全管理器,安全框架的核心组件,统筹realm/sessionManager/cache--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> <property name="sessionManager" ref="sessionManager"/> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 通过MethodInvokingFactoryBean工厂Bean,可以将指定方法返回值注入成为目标Bean的属性值。 将SecurityUtils的SecurityManager赋值--> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/> <property name="arguments" ref="securityManager"/> </bean> <!-- Shiro生命周期处理器--> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!--==============================================================================================================--> <!-- 基于Form表单的身份验证过滤器 --> <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"> <property name="usernameParam" value="username"/> <property name="passwordParam" value="password"/> <property name="loginUrl" value="/login.jsp"/> </bean> <!-- Shiro的Web过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/login.jsp"/> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> <property name="filters"> <util:map> <!--拦截表单,通过认证才能登录--> <entry key="authc" value-ref="formAuthenticationFilter"/> </util:map> </property> <property name="filterChainDefinitions"> <!-- ①[urls]部分的配置,其格式为:url=拦截器[参数],拦截器[参数]。 ②如果当前请求的url匹配[urls]部分的某个url模式,将会执行器配置的拦截器。 ③anon(anonymous)拦截器表示可以匿名访问。 ④authc(authencation)拦截器标识需要身份认证通过后才能访问。 ⑤logout(logout)拦截器表示登出/退出登录,它会清空shiro缓存信息。 ⑥url模式使用 Ant 风格模式: [1]?匹配一个字符; [2]*匹配零个或多个字符; [3]**匹配路径中的零个或多个路径;--> <value> /index.jsp = anon /unauthorized.jsp = anon /login.jsp = authc /logout = logout /** = user </value> </property> </bean></beans>
- 【shiro】--- spring整合shiro
- spring + Shiro 整合
- spring整合shiro
- Spring与Shiro整合
- spring 整合shiro
- shiro 整合spring
- Shiro+Spring MVC整合
- Shiro整合spring
- Shiro+Spring MVC整合
- Spring整合Shiro(一)
- Spring整合Shiro(二)
- shiro整合spring+springmvc
- shiro 整合 spring
- Shiro整合Spring maven
- Spring+Shiro权限整合
- Shiro与Spring整合
- shiro整合spring
- Spring整合Shiro
- 解释Java中的值传递
- POJ 1797 Heavy Transportion Dijkstra变形
- 静态变量初始化的时机
- (M)Dynamic Programming:2 Keys Keyboard
- bzoj1306
- shiro整合spring
- CSDN博客编辑用html记录
- BZOJ 2177 最小曼哈顿生成树
- 持续集成
- c++面试题
- Hibernate4 save方法无法保存数据
- 【bzoj2733】【HNOI2012】永无乡
- leetcode 336. Palindrome Pairs 回文数字符串对
- 命令行执行python文件时提示ImportError: No module named 'xxx'