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 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...
随机推荐
- 【leetcode】961. N-Repeated Element in Size 2N Array
题目如下: In a array A of size 2N, there are N+1 unique elements, and exactly one of these elements is r ...
- MySQL - primary key PK unique key,key PK index
primary key PK unique key 总结 primary key = unique + not null 主键不能为空每个字段值都不重复,unique可以为空,非空字段不重复 uniq ...
- QT--QSocketNotifier类介绍
QSocketNotifier 用来监听系统文件操作,将操作转换为Qt事件进入系统的消息循环队列.并调用预先设置的事件接受函数,处理事件. 一共存在3类事件:read,write,exceptio ...
- 3. 初识jmeter及JDK安装
jmeter 介绍 Apache JMeter™应用程序是开源软件,100%纯Java应用程序,旨在加载测试功能行为和测量性能.它最初是为测试Web应用程序而设计的,但后来扩展到其他测试功能. Jme ...
- setjmp与longjmp的分析
#include <setjmp.h> int main(int argc, const char* argv[]) { jmp_buf buf = {0,}; int k = 0; ...
- 『Golang』—— 标准库之 os
Golang 的 os 库基本承袭 Unix 下 C 语言的用法 path 库: func Base(path string) string //取文件名,不含目录部分 func Dir(path s ...
- java读取pdf文本转换html
补充:一下代码基于maven,现将依赖的jar包单独导出 地址:pdf jar 完整代码地址 也就两个文件 java读取pdf中的纯文字,这里使用的是pdfbox工具包 maven引入如下配置 < ...
- cm 安装cdh 后添加hive服务
cm 安装cdh 后添加hive服务,出现错误提示 添加服务时候hive 配置如下: 错误信息提示: 错误日志: xec /opt/cloudera/parcels/CDH-5.4.7-1.cdh5. ...
- 众所周知,static修饰的成员只实例化一次,而string类型每次赋值都会重新创建一个实例,那么用static修饰string呢?
string 类型每次实例化都会重新创建一个实例: 解释:string 类型重载了运算符 “=” ,每次 “=” 操作都是一次 “new”. static 修饰符的成员只实例化一次?? 解释:这个说法 ...
- mongo之$group+$addToSet
直接举例说明 #ArrangingResult表结构 { "_id" : ObjectId("5acc739df78bf21f8c94f080"), " ...