不知道我的web.xml 大家都理解了没。  废话确实有点多,可能很多知识点,大家都知道,可是我学的时候,压根什么都不懂啊....

这篇我们要讲刽子手  securityConfig。 为什么要说他是刽子手呢?  因为他是无良掌柜的小工,直接的操盘手......

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http access-denied-page = "/accessDenied.jsp"> <!-- 访问拒绝页面 -->
<form-login login-page="/login.jsp"/> <!-- 定义登陆界面 -->
<intercept-url pattern="/login.jsp" filters="none"/>
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/> <!-- 用户最大登录数设置为1 ,超过则引发异常 -->
</session-management>
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> <!-- 自定义FILTER ,FilterSecurityInterceptor 负责授权-->
</http>
<!-- myFilter -->
<beans:bean id = "myFilter" class = "com.qbt.spring.security.MyFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref ="authenticationManager"></beans:property> <!-- 登陆验证 ,验证你的用户名密码噼里啪啦-->
<beans:property name="securityMetadataSource" ref = "securityMetadataSource"></beans:property> <!-- 资源数据源的定义 ,神马权限对应神马资源 噼里啪啦-->
<beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean"></beans:property> <!-- 访问决策 有没有权限访问资源 噼里啪啦-->
</beans:bean> <!-- 验证配置,认证管理器,实现UserDetailService接口 -->
<!-- authenticationManager 可以有多个provider提供信息,我们用myUserDetailService获取信息 -->
<!-- Spring Security中进行身份验证的是AuthenticationManager接口,ProviderManager是它的一个默认实现,
但它并不用来处理身份认证,而是委托给配置好的AuthenticationProvider,每个AuthenticationProvider会轮流检查身份认证。
检查后或者返回Authentication对象或者抛出异常 -->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailService"></authentication-provider>
</authentication-manager> <!-- 获取user数据,可以从数据库中获取用户密码,角色等! -->
<beans:bean id = "myUserDetailService" class = "com.qbt.spring.security.MyUserDetailService"></beans:bean> <!-- 访问决策器,决定用户的角色,访问的权限 -->
<beans:bean id = "myAccessDecisionManagerBean" class = "com.qbt.spring.security.MyAccessDecisionManager"></beans:bean> <!-- 资源数据源的定义 什么资源对应什么权限,或者什么资源能被什么角色访问-->
<beans:bean id = "securityMetadataSource" class = "com.qbt.spring.security.MyInvocationSecurityMetadataSource"></beans:bean> </beans:beans>

可以看出来,这里的核心过滤器是我们自己实现的MyFilterSecurityInterceptor

//下面,贴出他的代码

package com.qbt.spring.security;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; /**
*登陆后,每次访问资源都会访问这个拦截器 ,执行doFilter, 调用invoke,
*super.beforeInvocation() 会调用SecurityMetadataSource 的getAttributes方法获取fi对应的所有权限,再调用decide的方法,判断是否有权限
*然后调用下一个拦截器。
*
*/
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{ //配置文件注入
private FilterInvocationSecurityMetadataSource securityMetadataSource; //登陆后,每次访问资源都通过这个拦截器拦截
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
} private void invoke(FilterInvocation fi) throws IOException, ServletException {
//fi 封装了request,response,chain
//里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
//再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); //这里的token里面到底是什么呢? 八一八 来!
/**
* 源码---
* protected InterceptorStatusToken beforeInvocation(Object object)
{
Assert.notNull(object, "Object was null"); //预言
//省略
Collection attributes = obtainSecurityMetadataSource().getAttributes(object);
//调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
if(attributes == null)
{
//抛异常省略
return null;
}
//省略
//判断是否需要对认证实体重新认证,默认为否
Authentication authenticated = authenticateIfRequired();
try
{//decide方法来校验用户的权限是否足够
accessDecisionManager.decide(authenticated, object, attributes);
}
catch(AccessDeniedException accessDeniedException)
{//抛异常
publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, accessDeniedException));
throw accessDeniedException;
}
//省略
return new InterceptorStatusToken(authenticated, true, attributes, object);
}
*
*/
try{
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally{
super.afterInvocation(token, null);
}
} @Override
public void init(FilterConfig arg0) throws ServletException { }
//相对应的MyAccessDecisionManager的supports方法必须放回true,否则会提醒类型错误
@Override
public Class<? extends Object> getSecureObjectClass() {
return FilterInvocation.class;
} @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
} public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource ){
this.securityMetadataSource = newSource;
} @Override
public void destroy() { }
}

//累啊...

然后我们来看看 authenticationManager

package com.qbt.spring.security;

import java.util.ArrayList;
import java.util.Collection; import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; public class MyUserDetailService implements UserDetailsService{ /**
* 获取用户信息,返回User放到Spring的全局缓存SecurityContentHolder中,让其他过滤器使用
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
UserDetails user = null;
Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>(); //定义一个权限集合
GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl("ROLE_ADMIN"); //定义一个管理员权限
GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("ROLE_USER"); //定义一个用户权限
System.out.println("**********MyUserDetailService登陆验证,通过用户名获取权限************");
if(username.equals("admin")){
auths.add(auth2);
auths.add(auth1);
}else{
auths.add(auth2);
}
// username, password, enable, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities
user = new User(username, "admin", true, true, true, true, auths);
return user;
} }

然后再看看MyInvocationSecurityMetadataSource

package com.qbt.spring.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher; /**
* @author ORC
* FilterInvocationSecurityMetadataSource 继承于 SecurityMetadataSource
*
*/ public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { private UrlMatcher urlMatcher = new AntUrlPathMatcher();
public static Map<String,Collection<ConfigAttribute>> resourceMap = null; public MyInvocationSecurityMetadataSource () {
loadResourceDefine();
} /**
* 获取角色和资源的相对应的关系,在tomcat启动时加载。
* 因为是在tomcat启动时就要加载,所以如果权限对应关系改变的话,就需要重新获取
* 如果要调用Dao的话,但是在启动的时候,这个Dao可能还没有加载
* 所以如果要在这里调用数据库的话,要自己写sessionfaction,sql/hql
* 还有一种方法就是,在getAttributes方法里调用Dao,因为这个方法是在tomcat启动之后才调用的
*/
private void loadResourceDefine() {
resourceMap = new HashMap<String,Collection<ConfigAttribute>>();
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
ConfigAttribute ca = new SecurityConfig("ROLE_USER");
atts.add(ca);
resourceMap.put("/index.jsp", atts);
Collection<ConfigAttribute> attsNo = new ArrayList<ConfigAttribute>();
ConfigAttribute no = new SecurityConfig("ROLE_NO");
attsNo.add(no);
resourceMap.put("/other.jsp", attsNo); System.out.println("*************MyInvocationSecurityMetadataSource 调用,获取角色和资源对应值*******************");
} @Override
public Collection<ConfigAttribute> getAttributes(Object obj) throws IllegalArgumentException {
String url = ((FilterInvocation)obj).getRequestUrl();
System.out.println("*************MyInvocationSecurityMetadataSource getAttribute调用,获取资源所对应的角色集合*******************");
Iterator<String>ite = resourceMap.keySet().iterator();
while(ite.hasNext()){
String resUrl = ite.next();
if(urlMatcher.pathMatchesUrl(resUrl, url)) {
return resourceMap.get(resUrl);
}
}
return null;
} @Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
} @Override
public boolean supports(Class<?> class1) {
return true;
} }

再看MyAccessDecisionManager

package com.qbt.spring.security;

import java.util.Collection;
import java.util.Iterator; import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; public class MyAccessDecisionManager implements AccessDecisionManager{ @Override
public void decide(Authentication authentication, Object obj, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if(configAttributes == null) {
return;
}
System.out.println("*************MyAccessDecesionManager 判断用户是否有权限**************");
Iterator<ConfigAttribute> itr = configAttributes.iterator();
while(itr.hasNext()){
ConfigAttribute ca = itr.next();
String needRole = ((SecurityConfig)ca).getAttribute();
for(GrantedAuthority ga : authentication.getAuthorities()){
if(needRole.equals(ga.getAuthority())){
return;
}
}
}
throw new AccessDeniedException("No Right");
} //这个 supports(ConfigAttribute) 方法在启动的时候被
//AbstractSecurityInterceptor调用,来决定AccessDecisionManager
//是否可以执行传递ConfigAttribute
@Override
public boolean supports(ConfigAttribute configattribute) {
return false;
}
//supports(Class)方法被安全拦截器实现调用,
//包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型。
@Override
public boolean supports(Class<?> class1) {
return true;
} }

Spring Security 从配置入门 学习讲解。刽子手------------securityConfig.xml的更多相关文章

  1. Spring Security 从配置入门 学习讲解。万恶之源------------web.xml

    这段时间,工作闲了下来,接触了Spring Security,对于我一个基础很差的人来说,无疑是个挑战啊. 经过一段时间的摸索,终于有了点眉目,在这里,要特别感谢http://blog.csdn.ne ...

  2. Spring Security 入门(1-2)Spring Security - 从 配置例子例子 开始我们的学习历程

    1.Spring Security 的配置文件 我们需要为 Spring Security 专门建立一个 Spring 的配置文件,该文件就专门用来作为 Spring Security 的配置. &l ...

  3. Spring Security极简入门三部曲(上篇)

    目录 Spring Security极简入门三部曲(上篇) 写在前面 为什么要用Spring Security 数据库设计 demo时刻 核心代码讲解 小结 Spring Security极简入门三部 ...

  4. SPRING SECURITY JAVA配置:Web Security

    在前一篇,我已经介绍了Spring Security Java配置,也概括的介绍了一下这个项目方方面面.在这篇文章中,我们来看一看一个简单的基于web security配置的例子.之后我们再来作更多的 ...

  5. Spring Security极简入门三部曲(中篇)

    目录 Spring Security极简入门三部曲(中篇) 验证流程 Authentication接口 过滤器链 AuthenticationProvider接口: demo时刻 代码讲解 小结 Sp ...

  6. Spring Security认证配置(三)

    学习本章之前,可以先了解下上篇Spring Security认证配置(二) 本篇想要达到这样几个目的: 1.登录成功处理 2.登录失败处理 3.调用方自定义登录后处理类型 具体配置代码如下: spri ...

  7. Spring Security认证配置(二)

    学习本章之前,可以先了解下上篇Spring Security基本配置. 本篇想要达到这样几个目的: 1.访问调用者服务时,如果是html请求,则跳转到登录页,否则返回401状态码和错误信息 2.调用方 ...

  8. Spring Security认证配置(一)

    学习本章之前,可以先了解下上篇 Spring Security基本配置. 本篇主要讲述Spring Security基于表单,自定义用户认证配置(上篇中的配置,本篇将不再阐述).一共分为三步: 1.处 ...

  9. spring的Java配置入门(Spring Boot学习笔记之一)

    spring的Java配置 1.创建maven项目 使用idea创建maven项目,这里顺便提一下,idea真的比eclipse好用,早点熟悉吧.然后就是maven是java项目管理最主流的工具,自己 ...

随机推荐

  1. shell下>和>>的区别

    >  :如果文件不存在,同上,如果文件存在,先将文件清空,然后将数据填入此文件 >> :如果文件不存在,将创建新的文件,并将数据送至此文件:如果文件存在,则将数据添加在文件后面

  2. .net 项目 调用webservice 出错,异常信息:对操作“xxx”的回复消息正文进行反序列化时出错。解决方案。

    项目运行好好的,增加并更新WebService后,出错,捕获异常信息为:对操作“xxx”的回复消息正文进行反序列化时出错.解决方案. 认真分析异常信息后,得到关键提醒: {"读取 XML 数 ...

  3. php empty,isset,is_null比较(差异与异同)

    php empty,isset,is_null比较(差异与异同)  http://www.cnblogs.com/chengmo/archive/2010/10/18/1854258.html

  4. rem

    "em"是相对于其父元素来设置字体大小的,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小,在我们多次使用时,就会带来无法预知的错误风险.而rem是相对于根元 ...

  5. mysql 安装以及运行

    目录: http://www.fenby.com/courses/mysqlke-cheng-lian-zai/ 1.下载 2.配置 3.启动服务器 4.启用客户端并修改用户信息 1.mysql的下载 ...

  6. Apache、NGINX支持中文URL

    Apache(32位):安装环境:CentOS 5.6 + Apache 2.2.15安装结果:安装后支持“中文图片.文件名”链接直接打开以下为安装过程:1.下载安装包 wget ftp://ftp. ...

  7. Linux上如何执行java程序

    想要在Ubuntu上运行java程序,可以将java程序编译成功后打包,然后在Ubuntu上用命令执行jar文件 具体操作如下: 1.Windows上使用eclipse编译java工程,编译完成后导出 ...

  8. FastReport 自定义数据集

    1.可以自定义一个新的数据源   参考: internal class VirtualDataSource : DataSourceBase {    private int FVirtualRows ...

  9. ListView

    ListView:列表展示数据1.视图 - 在其右上方小箭头点击将视图改为Largelcon:或右键属性在外观View将其改为Details2.设置列头 - 在其右上方小箭头点击选择编辑列,然后添加列 ...

  10. 通过pip安装模块

    环境:ubuntu,python2/3 命令: pip3 install ipy # 通过pip3给python3.x安装ipypip3 install --upgrade pip # 升级pippi ...