Spring-Security (学习记录四)--配置权限过滤器,采用数据库方式获取权限
完整代码见附件
1. 需要在spring-security.xml中配置验证过滤器,来取代spring-security.xml的默认过滤器
spring-security中需要配置验证过滤器来实现整个拦截的过程,其中需要配置一下三个来实现。
authenticationManager:在配置用户名和角色的时候,已经配置过了。 security:authentication-manager
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 (学习记录四)--配置权限过滤器,采用数据库方式获取权限的更多相关文章
- Spring Security 学习记录
一.核心拦截器详细说明 1.WebAsyncManagerIntegrationFilter 根据请求封装获取WebAsyncManager 从WebAsyncManager获取/注册Security ...
- leveldb 学习记录(四)Log文件
前文记录 leveldb 学习记录(一) skiplistleveldb 学习记录(二) Sliceleveldb 学习记录(三) MemTable 与 Immutable Memtablelevel ...
- [转]Spring Security学习总结二
原文链接: http://www.blogjava.net/redhatlinux/archive/2008/08/20/223148.html http://www.blogjava.net/red ...
- [转]Spring Security学习总结一
[总结-含源码]Spring Security学习总结一(补命名空间配置) Posted on 2008-08-20 10:25 tangtb 阅读(43111) 评论(27) 编辑 收藏 所属分 ...
- Spring security 学习 (自助者,天助之!)
自己努力,何必要强颜欢笑的求助别人呢? 手心向下不求人! Spring security学习有进展哦: 哈哈! 1.页面都是动态生产的吧! 2.设置权限: a:pom.xml配置jar包 b:cr ...
- Spring Security和 JWT两大利器来打造一个简易的权限系统。
写在前面 关于 Spring Security Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求.在Java EE领域,成熟的安全框架解决方案一般有 A ...
- Spring Security调研记录【七】--核心模型与实现
网上有非常多关于Spring Security文章中,都觉得Spring Security(相对于shiro)过于复杂,个人觉得复杂的是Spring Security的官方文档而不是Spring Se ...
- spring boot rest 接口集成 spring security(1) - 最简配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能
在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...
随机推荐
- Mysql学习笔记(004)- 条件查询
条件查询 #进阶2:条件查询 /* 语法: select 查询列表③ from 表名① where 条件筛选② 分类: 一.按条件表达式筛选 条件运算符:> < = != <> ...
- ( vant ) 新手踩坑
最近在用vant 做H5 页面,坑太他娘的坑娘啊!!!!!!!!!!!!!!!! 1,修改vant组件样式问题 vant 修改组件的样式时,在scoped 属性下没有效果.如果去掉scope 会造成全 ...
- Ubuntu 16.04系统上修改Docker镜像的存储路径 (转)
转自:https://blog.csdn.net/qihongchao/article/details/80651492 dba专门挂了一个硬盘让我放项目(测试环境)因为系统空间比较小,希望把dock ...
- Ubuntu下安装Samba服务器
闲来无聊尝试自己安装下Samba服务器,使本机和虚拟机可以无障碍传输文件(虽然用VMwaretools可传,但总感觉麻烦,而且速度欠佳) 首先,同安装qemu一样,在安装之前要确定你的系统apt列表已 ...
- PHP面试 PHP基础知识 七(文件及目录处理)
文件操作 文件打开函数 fopen()函数 //用来打开一个文件 打开时需要指定打开模式 语法:fopen( filename, mode, include_path, context); filen ...
- C++——异常
1.throw表达式 if (item1.isbn()!=item2.isbn()) throw runtime_error("data must refer to the same ISB ...
- hql 跟 sql 区别
hql 跟 sql 区别 1.hql与sql的区别 sql 面向数据库表查询 hql 面向对象查询 hql : from 后面跟的 类名+类对象 where 后 用对象的属性做条件 sql: fro ...
- 2-vim-打开和新建文件-01-打开/新建文件/打开定位到文件指定行
1.新建或打开文件 命令: vim 文件名 在终端中输入vi在后面跟上文件名即可. 如果文件已经存在,会直接打开文件. 如果文件不存在,会新建一个文件. 2.打开文件并定位到文件指定行. 命令: vi ...
- linux下读取移动硬盘
前提是安装了ntfs-3g软件,系统才能识别到移动硬盘. 第一步.fdisk -l 该命令查看系统识别到的磁盘,如果移动硬盘系统能够识别, 在屏幕上会输出“/dev/sdb1”之类的字样. ...
- Match & Catch CodeForces - 427D 后缀自动机水题
题意: 给出两个字符串a,b,求一个字符串,这个字符串是a和b的子串, 且只在a,b中出现一次,要求输出这个字符串的最小长度. 题解: 将a串放入后缀自动机中,然后记录一下每个节点对应的子串出现的次数 ...