- SecurityContextPersistenceFilter
- ConcurrentSessionFilter
- WebAsyncManagerIntegrationFilter
- HeaderWriterFilter
- CsrfFilter
- LogoutFilter
- UsernamePasswordAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- RememberMeAuthenticationFilter
- AnonymousAuthenticationFilter
- SessionManagementFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
如果要在我们自己的项目中整合SpringSecurity,,应该实现SpringSecurity里面的UserDetailsService,并且将USer权限authorities.add(new SimpleGrantedAuthority(role.getId()));将权限存放到实体的当中,同时User实体要实现UserDetails这个接口,这个接口里面的内容为:
package org.springframework.security.core.userdetails;
import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
public abstract interface UserDetails
extends Serializable
{
public abstract Collection<? extends GrantedAuthority> getAuthorities();//这个是权限相关
public abstract String getPassword();
public abstract String getUsername();
public abstract boolean isAccountNonExpired();
public abstract boolean isAccountNonLocked();
public abstract boolean isCredentialsNonExpired();
public abstract boolean isEnabled();
}
所在在User里获取相关权限代码可以这样写:
Collection authorities = new ArrayList();
List<Role> roles = user.getRoles();//获取该用户所拥有的权限
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getId()));
}
user.setAuthorities(authorities);
下面是SpringSecurity里面的实体User类:
package org.springframework.security.core.userdetails; import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.springframework.security.core.CredentialsContainer; import org.springframework.security.core.GrantedAuthority; import org.springframework.util.Assert; public class User implements UserDetails, CredentialsContainer { private static final long serialVersionUID = 320L; private String password; private final String username; private final Set<GrantedAuthority> authorities; private final boolean accountNonExpired; private final boolean accountNonLocked; private final boolean credentialsNonExpired; private final boolean enabled; public User(String username, String password, Collection<? extends GrantedAuthority> authorities) { this(username, password, true, true, true, true, authorities); } public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { if ((username == null) || ("".equals(username)) || (password == null)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.username = username; this.password = password; this.enabled = enabled; this.accountNonExpired = accountNonExpired; this.credentialsNonExpired = credentialsNonExpired; this.accountNonLocked = accountNonLocked; this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); } public Collection<GrantedAuthority> getAuthorities() { return this.authorities; } public String getPassword() { return this.password; } public String getUsername() { return this.username; } public boolean isEnabled() { return this.enabled; } public boolean isAccountNonExpired() { return this.accountNonExpired; } public boolean isAccountNonLocked() { return this.accountNonLocked; } public boolean isCredentialsNonExpired() { return this.credentialsNonExpired; } public void eraseCredentials() { this.password = null; } private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) { Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection"); SortedSet sortedAuthorities = new TreeSet(new User.AuthorityComparator(null)); for (GrantedAuthority grantedAuthority : authorities) { Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements"); sortedAuthorities.add(grantedAuthority); } return sortedAuthorities; } public boolean equals(Object rhs) { if ((rhs instanceof User)) { return this.username.equals(((User)rhs).username); } return false; } public int hashCode() { return this.username.hashCode(); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(super.toString()).append(": "); sb.append("Username: ").append(this.username).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); boolean first; if (!this.authorities.isEmpty()) { sb.append("Granted Authorities: "); first = true; for (GrantedAuthority auth : this.authorities) { if (!first) { sb.append(","); } first = false; sb.append(auth); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } }
上面列的这些就是SS整个的过滤器集合,15个,非常多,其实web开发用到的过滤器没有那么多。简单的说过滤器作用在这里体现的就是 “检验 请求(request) 和 响应 (response)”具体哪些是对开发人员是要熟悉的, 待我们验证完就知道了!
那么在SS中是如何工作的呢?
完成基本的配置工作:web.xml 配置SS的相关信息
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在web应用中,当浏览器发起一个请求到展现出一个页面的内容就是一个完成的请求和响应:
1、在这里过程中,request 是直接访问的资源URL, 未经过处理就返回了相关数据
2、或者是request 和 response 都经过了相关处理返回相关数据
SS就是走的第二种路, 在request和response都经过了一系列的处理。那么要处理这些请求和响应最好的方法就是Servlet过滤器了。至于处理了什么? 怎么处理的?我们再看!
SS 作为一种安全框架, 我们暂且先讨论的是web部分的安全问题,因为SS还可以给其他的客户端做安全处理。大概一个请求响应如下步骤:
1:浏览器的请求
2:过滤器拦截URL
3:认证授权
4:访问授权
一步步具体对这四个步骤进行解读
1、浏览器的请求
发起一个标准的http协议的请求URL “http://www.access.com/resource/accountlist";
上面的一个URL地址就是标准的HTTP协议的请求:协议头, 域名主体,端口80, 资源位置
2、过滤器拦截URL
这里就涉及到了过滤器了,很想知道的是从请求发起的URL被什么过滤器拦截了?
首页在SS中注册的过滤器有15种,即文章开头所列出来的,这15个过滤器分别被注入到了SS的过滤器链中,由Spring的IOC容器来管理。
并且如果我们自己自定义的过滤器,实现了其上的任意中一种,那么也一样会注入到SS的过滤器链中被维护起来。
所有的URL 都会经过这15个过滤器,每个过滤器执行不同的职责(比如:认证,授权,访问,内置对象的初始化等等)
进入到这个过滤器的前提是被请求的URL地址是要需要经过SS的,那么如何让URL经过这些过滤器的拦截的呢?
在Security.xml 配置文件中
<http pattern="/resources/**" security="none"/>
配置中所描述的就是以/resource/** 形式的URL 是不需要经过过滤器的处理的,其余的那么都会经过拦截器的处理。
在这里大概阐述下这些拦截器做了什么事情,只列出web方面要比较常用的。
过滤器 描述 SecurityContextPersistenceFilter存储每一个请求来的上下文对象,在身份验证之前调用 LogoutFilter 系统退出 UsernamePasswordAuthenticationFilter执行系统登录的过滤器,用来验证用户名密码 DefaultLoginPageGeneratingFilter 生成SS提供默认的登陆页面 SecurityContextHolderAwareRequestFilter 对容器的servlet进行包装,重新请求 AnonymousAuthenticationFilter 对SS的任何访问都要进行认证资源的初始化 FilterSecurityInterceptor经过SS验证后访问认证地址前的拦截器
3、认证授权
走到这里就很容易能想到,一个URL 要访问受保护的资源,那么可以反过来说这个URL 是要被许可,被认证的。那么在SS 中以用户 登录成功为准则,保存用户登录信息到SS中作为凭证,再是对要访问的资源进行校验来做到认证的可靠性。
SS中默认的授权方式是在SecurityContextPersistenceFilter过滤器拦截后创建系统认证对象,并传递到AnonymousAuthenticationFilter 过滤器进行认证对象数据的初始化值。到了这一步就相当于系统已经有了一个认证授权的对象。
4、访问授权
经过认证授权后,请求带着认真对象一并到了访问授权这步骤 AccessDecisionManager 决定如何对URL进行访问处理,FilterInvocationSecurityMetadataSource 已经存储了该URL对应的默认的权限资源。
如果请求的URL 是一个登陆处理 “/login”
在访问决定策略器决定处理期之前,会被UsernamePasswordAuthenticationFilter 拦截下来,看名字就知道是用户名和密码的认证过滤器
在过滤器中进行用户名和密码的验证,并把改用户名和密码组成的token存入认证对象AuthenticationManager管理器中。AuthenticationManager随后调用
this.getAuthenticationManager().authenticate(token);
意思是让认证管理器的认证方法去校验,即调用了UserDetail方法,查找权限,并返回一个User对象(SS自带的User对象)
同时在SS上下文中会存储这个认证后的对象,再进行AccessDecisionManager 的决定认证,首先会把认证用户的权限给取出来,然后再系统中预加载的URL对应的权限集合加载出来一一比对,如果符合则放行,且上下文中已经是认证有效的。可以通过SS的一些JSP标签获取认证后的用户信息。
如果请求的URL是一个非登陆处理的 “/XXX"
不像登陆处理的先被UsernamePasswordAuthenticationFilter 拦截, 此时经过这条拦截器不做任何处理,到了访问决策处理器的处理。改处理会把该URL所对应的权限集合加载出来,然后已预加载的认证对象里的认证资源(权限,资源)进行比对,当比对不成功就表示访问是失败的,则抛出访问异常,这些访问异常会被抽象类的调用者AbstractSecurityInterceptor 这个拦截器所捕捉。进行一个异常的处理,这种异常SS当做是认证异常,那么会从SS系统预留的URL中加载出登录页面的URL,如果配置的是/xxx.jsp, 那么就会跳转到/xxx.jsp登陆页面要求输入用户名和密码去校验。
提交表单到过滤器,就执行了登陆处理的“/login”和 登陆处理的流程是一样的。
相关推荐
spring security spring security 中文文档
Spring Security三份资料,实战Spring Security 3.x.pdf;Spring Security 3.pdf;Spring Security使用手册.pdf
Spring Security 演讲PPT(演讲嘉宾:张明星) WebSphere技术专家沙龙在广州圆满举办,WSC超级版主Fastzch(张明星)担任本次沙龙的演讲嘉宾,他给广州的WebSphere技术专家带来了以“Spring Security ”为主题的...
Spring Security in Action
该资源是基本Spring Security实战七篇文档中组织的源码,详情如下: ssecurity项目是Spring Security实战(一和二)的源码; ssecurity-db项目是Spring Security实战(三)的源码; ssceurity-page项目是Spring ...
三更springsecurity学习笔记
springsecurity是一个功能强大且高度可定制的身份验证和访问控制框架。springsecurity是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring安全性的真正威力在于它可以很容易地扩展以...
Spring Security 3.pdf Spring Security 3.pdf Spring Security 3.pdf Spring Security 3.pdf
理解Spring Security的工作原理,Spring Security结构总览,认证流程和授权,中间涉及到哪些组件,这些组件分 别处理什么,如何自定义这些组件满足个性需求。 OAuth2.0认证的四种模式?它们的大体流程是什么? ...
很多独立软件供应商,因为灵活的身份验证模式二选择Spring Security。这样做允许他们快速的集成到他们的终端客户需求的解决方案而不用进行大量工程或者改变客户的环境。如果上面的验证机制不符合你的需求,Spring ...
SpringSecurity学习总结源代码
SpringSecurity框架的权限认证流程原理,请求到来时SpringSecurity如果调用层层过滤器来完成认证;
Spring Security。 官网 Spring Security API(Spring Security 开发文档).CHM
SpringSecurity课程文档下载 pdf 教学
SpringSecurity入门到进阶到高级,是我们老师给我们讲课用的,我们都照着配就没有问题,可以跑通,
spring security3 中文版本
Spring Security 2.0.x 参考手册 中文版
spring security2.5 jar 和spring security2.5 整合必须的jar包
教程视频:spring提供的安全权限框架,Spring Security、Spring Social 、Spring Security OAuth
1.本项目为SpringCloud Gateway的微服务框架,整合了SpringSecurity,微服务间使用Redis来获取登陆的用户信息。 2.由于Gat