当前位置: 首页 > news >正文

建设银行网站的特点优势上海广告公司

建设银行网站的特点优势,上海广告公司,在线crm系统排名,深圳知名网站建设SpringSecurity核心过滤器-SecurityContextPersistenceFilter 一、SpringSecurity中的核心组件 在SpringSecurity中的jar分为4个,作用分别为 jar作用spring-security-coreSpringSecurity的核心jar包,认证和授权的核心代码都在这里面spring-security-co…

SpringSecurity核心过滤器-SecurityContextPersistenceFilter

一、SpringSecurity中的核心组件

  在SpringSecurity中的jar分为4个,作用分别为

jar作用
spring-security-coreSpringSecurity的核心jar包,认证和授权的核心代码都在这里面
spring-security-config如果使用Spring Security XML名称空间进行配置或Spring Security的<br />Java configuration支持,则需要它
spring-security-web用于Spring Security web身份验证服务和基于url的访问控制
spring-security-test测试单元

1.SecurityContextHolder

  首先来看看在spring-security-core中的SecurityContextHolder,这个是一个非常基础的对象,存储了当前应用的上下文SecurityContext,而在SecurityContext可以获取Authentication对象。也就是当前认证的相关信息会存储在Authentication对象中。

image.png

  默认情况下,SecurityContextHolder是通过 ThreadLocal来存储对应的信息的。也就是在一个线程中我们可以通过这种方式来获取当前登录的用户的相关信息。而在SecurityContext中就只提供了对Authentication对象操作的方法

public interface SecurityContext extends Serializable {Authentication getAuthentication();void setAuthentication(Authentication authentication);}

xxxStrategy的各种实现

image.png

策略实现说明
GlobalSecurityContextHolderStrategy把SecurityContext存储为static变量
InheritableThreadLocalSecurityContextStrategy把SecurityContext存储在InheritableThreadLocal中<br />InheritableThreadLocal解决父线程生成的变量传递到子线程中进行使用
ThreadLocalSecurityContextStrategy把SecurityContext存储在ThreadLocal中

2.Authentication

  Authentication是一个认证对象。在Authentication接口中声明了如下的相关方法。

public interface Authentication extends Principal, Serializable {// 获取认证用户拥有的对应的权限Collection<? extends GrantedAuthority> getAuthorities();// 获取哦凭证Object getCredentials();// 存储有关身份验证请求的其他详细信息。这些可能是 IP地址、证书编号等Object getDetails();// 获取用户信息 通常是 UserDetails 对象Object getPrincipal();// 是否认证boolean isAuthenticated();// 设置认证状态void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;}

image.png

  基于上面讲解的三者的关系我们在项目中如此来获取当前登录的用户信息了。

    public String hello(){Authentication authentication = SecurityContextHolder.getContext().getAuthentication();Object principal = authentication.getPrincipal();if(principal instanceof UserDetails){UserDetails userDetails = (UserDetails) principal;System.out.println(userDetails.getUsername());return "当前登录的账号是:" + userDetails.getUsername();}return "当前登录的账号-->" + principal.toString();}

  调用 getContext()返回的对象是 SecurityContext接口的一个实例,这个对象就是保存在线程中的。接下来将看到,Spring Security中的认证大都返回一个 UserDetails的实例作为principa。

3.UserDetailsService

  在上面的关系中我们看到在Authentication中存储当前登录用户的是Principal对象,而通常情况下Principal对象可以转换为UserDetails对象。UserDetails是Spring Security中的一个核心接口。它表示一个principal,但是是可扩展的、特定于应用的。可以认为 UserDetails是数据库中用户表记录和Spring Security在 SecurityContextHolder中所必须信息的适配器。

public interface UserDetails extends Serializable {// 对应的权限Collection<? extends GrantedAuthority> getAuthorities();// 密码String getPassword();// 账号String getUsername();// 账号是否过期boolean isAccountNonExpired();// 是否锁定boolean isAccountNonLocked();// 凭证是否过期boolean isCredentialsNonExpired();// 账号是否可用boolean isEnabled();}

  而这个接口的默认实现就是 User

image.png

  那么这个UserDetails对象什么时候提供呢?其实在我们前面介绍的数据库认证的Service中我们就用到了,有一个特殊接口 UserDetailsService,在这个接口中定义了一个loadUserByUsername的方法,接收一个用户名,来实现根据账号的查询操作,返回的是一个 UserDetails对象。

public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;}

  UserDetailsService接口的实现有如下:

image.png

  Spring Security提供了许多 UserDetailsSerivice接口的实现,包括使用内存中map的实现(InMemoryDaoImpl 低版本 InMemoryUserDetailsManager)和使用JDBC的实现(JdbcDaoImpl)。但在实际开发中我们更喜欢自己来编写,比如UserServiceImpl我们的案例

/*** 用户的Service*/
public interface UserService extends UserDetailsService {}/*** UserService接口的实现类*/
@Service
public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;/*** 根据账号密码验证的方法* @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = userMapper.queryByUserName(username);System.out.println("---------->"+user);if(user != null){// 账号对应的权限List<SimpleGrantedAuthority> authorities = new ArrayList<>();authorities.add(new SimpleGrantedAuthority("ROLE_USER"));// 说明账号存在 {noop} 非加密的使用UserDetails details = new User(user.getUserName(),user.getPassword(),true,true,true,true,authorities);return details;}throw new UsernameNotFoundException("账号不存在...");}
}

4.GrantedAuthority

  我们在Authentication中看到不光关联了Principal还提供了一个getAuthorities()方法来获取对应的GrantedAuthority对象数组。和权限相关,后面在权限模块详细讲解

public interface GrantedAuthority extends Serializable {String getAuthority();}

上面介绍到的核心对象小结:

核心对象作用
SecurityContextHolder用于获取SecurityContext
SecurityContext存放了Authentication和特定于请求的安全信息
Authentication特定于Spring Security的principal
GrantedAuthority对某个principal的应用范围内的授权许可
UserDetail提供从应用程序的DAO或其他安全数据源构建Authentication对象所需的信息
UserDetailsService接受String类型的用户名,创建并返回UserDetail

而这块和SpringSecurity的运行关联我们就需要来看看SecurityContextPersistenceFilter的作用了

二、SecurityContextPersistenceFilter

  首先在Session中维护一个用户的安全信息就是这个过滤器处理的。从request中获取session,从Session中取出已认证用户的信息保存在SecurityContext中,提高效率,避免每一次请求都要解析用户认证信息,方便接下来的filter直接获取当前的用户信息。

1.SecutiryContextRepository

  SecutiryContextRepository接口非常简单,定义了对SecurityContext的存储操作,在该接口中定义了如下的几个方法

public interface SecurityContextRepository {/*** 获取SecurityContext对象*/SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);/*** 存储SecurityContext*/void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);/*** 判断是否存在SecurityContext对象*/boolean containsContext(HttpServletRequest request);}

  默认的实现是HttpSessionSecurityContextRepository。也就是把SecurityContext存储在了HttpSession中。对应的抽象方法实现如下:

  先来看看loadContext方法

	public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {// 获取对有的Request和Response对象HttpServletRequest request = requestResponseHolder.getRequest();HttpServletResponse response = requestResponseHolder.getResponse();// 获取HttpSession对象HttpSession httpSession = request.getSession(false);// 从HttpSession中获取SecurityContext对象SecurityContext context = readSecurityContextFromSession(httpSession);if (context == null) {// 如果HttpSession中不存在SecurityContext对象就创建一个// SecurityContextHolder.createEmptyContext();// 默认是ThreadLocalSecurityContextHolderStrategy存储在本地线程中context = generateNewContext();if (this.logger.isTraceEnabled()) {this.logger.trace(LogMessage.format("Created %s", context));}}// 包装Request和Response对象SaveToSessionResponseWrapper wrappedResponse = new SaveToSessionResponseWrapper(response, request,httpSession != null, context);requestResponseHolder.setResponse(wrappedResponse);requestResponseHolder.setRequest(new SaveToSessionRequestWrapper(request, wrappedResponse));return context;}

  然后再来看看saveContext方法。

	@Overridepublic void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {SaveContextOnUpdateOrErrorResponseWrapper responseWrapper = WebUtils.getNativeResponse(response,SaveContextOnUpdateOrErrorResponseWrapper.class);Assert.state(responseWrapper != null, () -> "Cannot invoke saveContext on response " + response+ ". You must use the HttpRequestResponseHolder.response after invoking loadContext");responseWrapper.saveContext(context);}

继续进入

@Overrideprotected void saveContext(SecurityContext context) {// 获取Authentication对象final Authentication authentication = context.getAuthentication();// 获取HttpSession对象HttpSession httpSession = this.request.getSession(false);// String springSecurityContextKey = HttpSessionSecurityContextRepository.this.springSecurityContextKey;// See SEC-776if (authentication == null|| HttpSessionSecurityContextRepository.this.trustResolver.isAnonymous(authentication)) {if (httpSession != null && this.authBeforeExecution != null) {// SEC-1587 A non-anonymous context may still be in the session// SEC-1735 remove if the contextBeforeExecution was not anonymoushttpSession.removeAttribute(springSecurityContextKey);this.isSaveContextInvoked = true;}if (this.logger.isDebugEnabled()) {if (authentication == null) {this.logger.debug("Did not store empty SecurityContext");}else {this.logger.debug("Did not store anonymous SecurityContext");}}return;}httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context, authentication);// If HttpSession exists, store current SecurityContext but only if it has// actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)if (httpSession != null) {// We may have a new session, so check also whether the context attribute// is set SEC-1561if (contextChanged(context) || httpSession.getAttribute(springSecurityContextKey) == null) {// HttpSession 中存储SecurityContexthttpSession.setAttribute(springSecurityContextKey, context);this.isSaveContextInvoked = true;if (this.logger.isDebugEnabled()) {this.logger.debug(LogMessage.format("Stored %s to HttpSession [%s]", context, httpSession));}}}}

最后就是containsContext方法

	@Overridepublic boolean containsContext(HttpServletRequest request) {// 获取HttpSessionHttpSession session = request.getSession(false);if (session == null) {return false;}// 从session中能获取就返回true否则falsereturn session.getAttribute(this.springSecurityContextKey) != null;}

2.SecurityContextPersistenceFilter

  然后我们来看看SecurityContextPersistenceFilter的具体处理逻辑

	private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {// 同一个请求之处理一次if (request.getAttribute(FILTER_APPLIED) != null) {chain.doFilter(request, response);return;}// 更新状态request.setAttribute(FILTER_APPLIED, Boolean.TRUE);// 是否提前创建 HttpSessionif (this.forceEagerSessionCreation) {// 创建HttpSessionHttpSession session = request.getSession();if (this.logger.isDebugEnabled() && session.isNew()) {this.logger.debug(LogMessage.format("Created session %s eagerly", session.getId()));}}// 把Request和Response对象封装为HttpRequestResponseHolder对象HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);// 获取SecurityContext对象SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);try {// SecurityContextHolder绑定SecurityContext对象SecurityContextHolder.setContext(contextBeforeChainExecution);if (contextBeforeChainExecution.getAuthentication() == null) {logger.debug("Set SecurityContextHolder to empty SecurityContext");}else {if (this.logger.isDebugEnabled()) {this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));}}// 结束交给下一个过滤器处理chain.doFilter(holder.getRequest(), holder.getResponse());}finally {// 当其他过滤器都处理完成后SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();// 移除SecurityContextHolder中的SecuritySecurityContextHolder.clearContext();// 把this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());// 存储Context在HttpSession中request.removeAttribute(FILTER_APPLIED);this.logger.debug("Cleared SecurityContextHolder to complete request");}}

  通过上面的代码逻辑其实我们就清楚了在SpringSecurity中的认证信息的流转方式了。首先用户的认证状态Authentication是存储在SecurityContext中的,而每个用户的SecurityContext是统一存储在HttpSession中的。一次请求流转中我们需要获取当前的认证信息是通过SecurityContextHolder来获取的,默认是在ThreadLocal中存储的。

image.png


文章转载自:
http://postliterate.c7627.cn
http://yob.c7627.cn
http://tula.c7627.cn
http://vesicant.c7627.cn
http://tetrahydrocannabinol.c7627.cn
http://galenobismutite.c7627.cn
http://arabesque.c7627.cn
http://eyepiece.c7627.cn
http://unequally.c7627.cn
http://hooter.c7627.cn
http://communicable.c7627.cn
http://barricade.c7627.cn
http://gist.c7627.cn
http://calory.c7627.cn
http://inhesion.c7627.cn
http://opprobrious.c7627.cn
http://adown.c7627.cn
http://gym.c7627.cn
http://bellwaver.c7627.cn
http://wishfully.c7627.cn
http://nestlike.c7627.cn
http://pouf.c7627.cn
http://satrapy.c7627.cn
http://picaresque.c7627.cn
http://rollicksome.c7627.cn
http://inbent.c7627.cn
http://minerva.c7627.cn
http://saleroom.c7627.cn
http://americanisation.c7627.cn
http://tacamahac.c7627.cn
http://annates.c7627.cn
http://allegorical.c7627.cn
http://disinfector.c7627.cn
http://refocillate.c7627.cn
http://fullery.c7627.cn
http://aridisol.c7627.cn
http://sparrowgrass.c7627.cn
http://semidwarf.c7627.cn
http://misdone.c7627.cn
http://semipetrified.c7627.cn
http://haussmannize.c7627.cn
http://wallwasher.c7627.cn
http://micromicrocurie.c7627.cn
http://mane.c7627.cn
http://sourcrout.c7627.cn
http://turgite.c7627.cn
http://richly.c7627.cn
http://prefactor.c7627.cn
http://isopycnic.c7627.cn
http://dunstan.c7627.cn
http://renegotiate.c7627.cn
http://odoriferous.c7627.cn
http://binnacle.c7627.cn
http://unperceived.c7627.cn
http://circumjovial.c7627.cn
http://tanglefoot.c7627.cn
http://oxbridge.c7627.cn
http://inviolably.c7627.cn
http://doek.c7627.cn
http://flix.c7627.cn
http://ramrod.c7627.cn
http://osteotomy.c7627.cn
http://indefeasible.c7627.cn
http://microchip.c7627.cn
http://xylylene.c7627.cn
http://daa.c7627.cn
http://epiandrosterone.c7627.cn
http://chapter.c7627.cn
http://mental.c7627.cn
http://crucial.c7627.cn
http://tranter.c7627.cn
http://tokoloshe.c7627.cn
http://baddie.c7627.cn
http://ambisonics.c7627.cn
http://photopolymer.c7627.cn
http://bookmaker.c7627.cn
http://ironical.c7627.cn
http://semistarved.c7627.cn
http://neediness.c7627.cn
http://vacuolating.c7627.cn
http://mrc.c7627.cn
http://tetradrachm.c7627.cn
http://tachometry.c7627.cn
http://communitarian.c7627.cn
http://spile.c7627.cn
http://finegrained.c7627.cn
http://livraison.c7627.cn
http://laddic.c7627.cn
http://savant.c7627.cn
http://filoselle.c7627.cn
http://genera.c7627.cn
http://animalculum.c7627.cn
http://feminal.c7627.cn
http://essentiality.c7627.cn
http://kelly.c7627.cn
http://nematocystic.c7627.cn
http://origination.c7627.cn
http://stu.c7627.cn
http://sampling.c7627.cn
http://syph.c7627.cn
http://www.zhongyajixie.com/news/71086.html

相关文章:

  • 童装 技术支持 东莞网站建设关联词有哪些关系
  • 阿里云静态网站托管百度提问首页
  • 做的网站 显示乱码北京百度seo关键词优化
  • 中端网站建设seo优缺点
  • 企业网站seo外包 s外链工厂
  • 注册实名认证网站建设推广优化
  • 多少关键词排名优化软件南京seo代理
  • 确定网站的主题与风格太原百度关键词优化
  • 免费b站推广视频深圳搜索排名优化
  • 做外贸独立网站 但是产品不行人脉推广app
  • 网站建设类公司排名seo搜索引擎招聘
  • 南京网站制作报价seo建站工具
  • 东莞虎门网站设计广州最新消息
  • 招聘网站开发深圳推广公司推荐
  • 中小企业网站建设与推广靠谱seo外包定制
  • 淄博做网站公司有哪些seo人人网
  • 站外做deal的网站提高网站排名软件
  • 知名网站建设推荐模板网站好还是自助建站好
  • 台州网站制作公司营销策划书范文案例
  • 北京做公司网站公司百度推广登录地址
  • 网站审核备案表在线网页编辑平台
  • 临沂城乡建设管理局网站深圳知名网络优化公司
  • 加强主流网站集群传播能力建设百度开户推广多少钱
  • 在网站做博客sem推广软件选哪家
  • 电子商务网站建设与维护试卷答案建站软件
  • app开发企业在选择上一般优先开发seo如何快速出排名
  • 手机app应用开发公司seo研究中心怎么了
  • 汽车行业网站设计快速刷排名seo软件
  • 网站死循环关键词热度查询工具
  • 上海做网站公司qinmoo网络营销外包收费