Spring-Security (学习记录四)--配置权限过滤器,采用数据库方式获取权限
2016-08-29 10:38
495 查看
完整代码见附件
[Toc]
1. 需要在spring-security.xml中配置验证过滤器,来取代spring-security.xml的默认过滤器
spring-security中需要配置验证过滤器来实现整个拦截的过程,其中需要配置一下三个来实现。authenticationManager:在配置用户名和角色的时候,已经配置过了。
accessDecisionManager:用来判断url是否有权限
securityMetadataSource:可以通过url得到角色名称
<!-- 配置 验证过滤器, 此过滤器取代系统的XML权限过滤 , 此过滤器配置完毕之后存放到 系统缺省的过滤链中--> <bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> <!-- 需要认证管理器, 通过它可以获取 管理员已经拥有的角色信息 , 由于id已经被org.springframework.security.authenticationManager默认了。不能更改,所以用别名--> <property name="authenticationManager" ref="authenticationManager"></property> <!-- 决策器 --> <property name="accessDecisionManager" ref="roleAccessDecisionManager" /> <!-- 配置urlService ,security可以通过url得到角色名称 --> <property name="securityMetadataSource" ref="urlService" /> </bean>
2. 配置securityMetadataSource,可以通过url来获取角色名称
package com.hp.service.impl; import java.util.Collection; import java.util.HashSet; import java.util.Set; import javax.annotation.Resource; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import com.hp.dao.UrlDao; import com.hp.model.Role; import com.hp.model.Url; import com.hp.service.UrlService; /** * 通过URL地址获取相应权限然后在获取相应的角色集合 * * 需要实现FilterInvocationSecurityMetadataSource接口 * * @author baojulin * */ @Service("urlService") public class UrlServiceImpl implements UrlService, FilterInvocationSecurityMetadataSource { @Resource private UrlDao urlDao; @Override public Url getRoleByUrl(String url) { return urlDao.getRoleByUrl(url); } /** * 此方法就是通过url地址获取 角色信息的方法 */ @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { // 获取当前的URL地址 System.out.println("object的类型为:" + object.getClass()); FilterInvocation filterInvocation = (FilterInvocation) object; String url = filterInvocation.getRequestUrl(); System.out.println("访问的URL地址为(包括参数):" + url); url = filterInvocation.getRequest().getServletPath(); System.out.println("访问的URL地址为:" + url); Url urlObject = getRoleByUrl(url); //调用自己实现的方法来url System.out.println("urlObject:" + urlObject); if (urlObject != null && urlObject.getPrivilege() != null) { Set<Role> roles = urlObject.getPrivilege().getRoles(); Collection<ConfigAttribute> c = new HashSet<ConfigAttribute>(); c.addAll(roles); return c; // 将privilege中的roles改为Collection<ConfigAttribute>,role需要实现ConfigAttribute接口 } else { // 如果返回为null则说明此url地址不需要相应的角色就可以访问, 这样Security会放行 return null; } } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { // TODO Auto-generated method stub return null; } /** * 如果为真则说明支持当前格式类型,才会到上面的 getAttributes 方法中 */ @Override public boolean supports(Class<?> clazz) { // TODO Auto-generated method stub // 需要返回true表示支持 return true; } }
urlDao中的实现
/** * 通过URL地址获取相应权限然后在获取相应的角色集合 */ @Override public Url getRoleByUrl(String url) { String hql = "FROM Url u JOIN FETCH u.privilege up JOIN FETCH up.roles WHERE u.url=:url"; Session session = sessionFactory.openSession(); return (Url) session.createQuery(hql).setString("url", url).uniqueResult(); }
3. 配置决策器:roleAccessDecisionManager
package com.hp.service.impl; import java.util.Collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; /** * 此类是决策器: 用来对 用户应有的角色,与URL地址可以访问的角色进行对比,如果不匹配则抛出异常 * * @author baojulin * */ @Service("roleAccessDecisionManager") public class RoleAccessDecisionManager implements AccessDecisionManager { protected final Log logger = LogFactory.getLog(RoleAccessDecisionManager.class); /** * 决策方法: 如果方法执行完毕没有抛出异常,则说明可以放行, 否则抛出异常 AccessDeniedException */ @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { // System.out.println("---------------decide------------------"); // 如果登陆成功,则信息会存储在Authorities中 Collection<? extends GrantedAuthority> myRoles = authentication.getAuthorities(); // 如果前面的 getAttributes() 返回非空,则返回的数据做为形参传入, 如果返回为null 则不会进入decide() 直接放行 // System.out.println("myRole:" + myRoles); // System.out.println("sysRole:" + configAttributes); for (GrantedAuthority myRole : myRoles) {// 当前登录的角色 for (ConfigAttribute urlRoles : configAttributes) {// 前台传入的url的角色,UrlDaoImpl.getAttributes获得的 if (myRole.getAuthority().equals(urlRoles.getAttribute())) { // 说明此URL地址符合权限,可以放行 return; } } } // System.out.println("-----权限验证失败------"); logger.error("-----权限验证失败------"); throw new AccessDeniedException("权限越界!"); } /** * 返回true表示支持 */ @Override public boolean supports(ConfigAttribute attribute) { // System.out.println("public boolean supports(ConfigAttribute attribute)"); return true; } /** * 返回true表示支持 */ @Override public boolean supports(Class<?> clazz) { // System.out.println("public boolean supports(Class<?> clazz)"); return true; } }
4. 在配置文件中,修改默认过滤器,将xml方式配置的权限去掉,改用数据库
<security:http auto-config="false" use-expressions="true" access-denied-page="/login.jsp?error=access-denied-page"> <!-- xml配置,配置的 pattern="/admin/**" 表示需要登录才能访问,而登录的角色为ROLE_ADMIN <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/user/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" /> --> <!-- 增加权限过滤器,采用数据库方式获取权限 --> <security:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/> <!-- 默认登录地址:j_spring_security_check --> <security:form-login default-target-url="/index.jsp" username-parameter="username" password-parameter="password" authentication-failure-url="/login.jsp?error=authentication-failure-url" login-page="/login.jsp"/> <!-- 注销也是由,Security框架来实现,LogoutFilter ,默认地址j_spring_security_logout --> <security:logout logout-success-url="/login.jsp"/> </security:http>
5. 图解spring-security整个流程
百度云链接:http://pan.baidu.com/s/1cBTdb4 密码:pjzk
相关文章推荐
- Spring-Security (学习记录五)--配置登录时,密码采用md5加密,以及获取登录信息属性监听同步自己想要的登录信息
- spring boot 集成quartz 2.0 实现前端动态配置(获取spring上下文)的两种方式,启动数据库中已开启定时任务
- 微软企业库5.0 学习之路——第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中)
- Spring-Security (学习记录六)--采用ehcache缓存UserDetails
- [EntLib]微软企业库5.0 学习之路——第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中)
- Spring Boot Security 学习笔记-根据登陆人动态配置权限-密码加密验证
- spring boot 集成quartz 2.0 实现前端动态配置(获取spring上下文)的两种方式,启动数据库中已开启定时任务
- JavaWeb之JDBC(二)采用读取配置文件方式编写JDBC的工具类,获取数据库的连接
- Spring-Security (学习记录三)--读取数据库中的用户和角色
- spring学习笔记12----Spring+jdbc组合开发( 采用基于xml方式配置事务)
- Spring---->采用静态配置文件方式实现AOP
- Spring Security ACL使用MySQL配置与数据库脚本
- 权限控制:spring 3.0 security配置例子
- spring_security之Web权限配置
- 【转】Android获取用于操作数据库的SQLiteDatabase实例【学习记录】
- spring读取配置文件,获取bean的几种方式
- Java 学习笔记14:Spring 数据库数据源DBCP配置说明
- 【学习】Spring 的 AOP :基于Annotation 的“零配置”方式
- Spring 采用基于XML方式配置事务
- Spring Security ACL使用Oracle数据库的配置与数据库脚本