Spring Security 工作原理概览,springboot面试知识点总结

这是配置登录相关的操作从方法名可知,配置了登录页请求路径,密码属性名,用户名属性名,和登录请求路径,permitAll()代表任意用户可访问。

http

.authorizeRequests()

.antMatchers(“/test”).hasRole(“test”)

.anyRequest().authenticated()

.accessDecisionManager(accessDecisionManager());

以上配置是权限相关的配置,配置了一个 /test url 该有什么权限才能访问, anyRequest() 表示所有请求,authenticated() 表示已登录用户才能访问, accessDecisionManager() 表示绑定在 url 上的鉴权管理器

为了对比,现在贴出另一个权限配置清单:

http.authorizeRequests()

.antMatchers(“/tets_a/“,”/test_b/”).hasRole(“test”)

.antMatchers(“/a/“,”/b/”).authenticated()

.accessDecisionManager(accessDecisionManager())

我们可以看到权限配置的自由度很高,鉴权管理器可以绑定到任意 url 上;而且可以硬编码各种 url 权限:

http

.logout()

.logoutUrl(“/logout”)

.logoutSuccessHandler(new MyLogoutSuccessHandler())

登出相关配置,这里配置了登出 url 和登出成功处理器:

http

.exceptionHandling()

.accessDeniedHandler(new MyAccessDeniedHandler());

上面代码是配置鉴权失败的处理器。

http.addFilterAfter(new MyFittler(), LogoutFilter.class);

http.addFilterAt(getAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);

上面代码展示如何在过滤器链中插入自己的过滤器,addFilterBefore 加在对应的过滤器之前,addFilterAfter 加在对应的过滤器之后,addFilterAt 加在过滤器同一位置,事实上框架原有的 Filter 在启动 HttpSecurity 配置的过程中,都由框架完成了其一定程度上固定的配置,是不允许更改替换的。根据测试结果来看,调用 addFilterAt 方法插入的 Filter ,会在这个位置上的原有 Filter 之前执行。

注:关于 HttpSecurity 使用的是链式编程,其中 http.xxxx.and.yyyyy 这种写法和 http.xxxx;http.yyyy 写法意义一样。

  • 自定义 AuthenticationManager 和 AccessDecisionManager

重写 authenticationManagerBean() 方法,并构造一个 authenticationManager:

@Override

public AuthenticationManager authenticationManagerBean() throws Exception {

ProviderManager authenticationManager = new ProviderManager(Arrays.asLis(getMyAuthenticationProvider(),daoAuthenticationProvider()));

return authenticationManager;

}

我这里给 authenticationManager 配置了两个认证器,执行过程参考流程图。

定义构造AccessDecisionManager的方法并在配置类中调用,配置参考 configure(HttpSecurity http) 说明:

public AccessDecisionManager accessDecisionManager(){

List<AccessDecisionVoter<? extends Object>> decisionVoters

= Arrays.asList(

new MyExpressionVoter(),

new WebExpressionVoter(),

new RoleVoter(),

new AuthenticatedVoter());

return new UnanimousBased(decisionVoters);

}

投票管理器会收集投票器投票结果做统计,最终结果大于等于0代表通过;每个投票器会返回三个结果:-1(反对),0(通过),1(赞成)。

Security 权限系统

=============

  • UserDetails

Security 中的用户接口,我们自定义用户类要实现该接口。

  • GrantedAuthority

Security 中的用户权限接口,自定义权限需要实现该接口:

public class MyGrantedAuthority implements GrantedAuthority {

private String authority;

}

authority 表示权限字段,需要注意的是在 config 中配置的权限会被加上 ROLE_ 前缀,比如我们的配置 authorizeRequests().antMatchers("/test").hasRole("test"),配置了一个 test 权限但我们存储的权限字段(authority)应该是 ROLE_test

  • UserDetailsService

Security 中的用户 Service,自定义用户服务类需要实现该接口:

@Service

public class MyUserDetailService implements UserDetailsService {

@Override

public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

return…

}

}

loadUserByUsername的作用在上文中已经说明,就是根据用户名查询用户对象。

  • SecurityContextHolder

用户在完成登录后 Security 会将用户信息存储到这个类中,之后其他流程需要得到用户信息时都是从这个类中获得,用户信息被封装成 SecurityContext ,而实际存储的类是 SecurityContextHolderStrategy ,默认的SecurityContextHolderStrategy 实现类是 ThreadLocalSecurityContextHolderStrategy 它使用了ThreadLocal来存储了用户信息。

手动填充 SecurityContextHolder 示例:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(“test”,“test”,list);

SecurityContextHolder.getContext().setAuthentication(token);

对于使用 token 鉴权的系统,我们就可以验证token后手动填充SecurityContextHolder,填充时机只要在执行投票器之前即可,或者干脆可以在投票器中填充,然后在登出操作中清空SecurityContextHolder。

Security 扩展

===========

Security 可扩展的有

  1. 鉴权失败处理器

  2. 验证器

  3. 登录成功处理器

  4. 投票器

  5. 自定义token处理过滤器

  6. 登出成功处理器

  7. 登录失败处理器

  8. 自定义 UsernamePasswordAuthenticationFilter

  • 鉴权失败处理器

Security 鉴权失败默认跳转登录页面,我们可以实现 AccessDeniedHandler 接口,重写 handle() 方法来自定义处理逻辑;然后参考配置类说明将处理器加入到配置当中。

  • 验证器

实现 AuthenticationProvider 接口来实现自己验证逻辑。需要注意的是在这个类里面就算你抛出异常,也不会中断验证流程,而是算你验证失败,我们由流程图知道,只要有一个验证器验证成功,就算验证成功,所以你需要留意这一点。

  • 登录成功处理器

在 Security 中验证成功默认跳转到上一次请求页面或者路径为 “/” 的页面,我们同样可以自定义:继承 SimpleUrlAuthenticationSuccessHandler 这个类或者实现 AuthenticationSuccessHandler 接口。我这里建议采用继承的方式,SimpleUrlAuthenticationSuccessHandler 是默认的处理器,采用继承可以契合里氏替换原则,提高代码的复用性和避免不必要的错误。

  • 投票器

投票器可继承 WebExpressionVoter 或者实现 AccessDecisionVoter接口;WebExpressionVoter 是 Security 默认的投票器;我这里同样建议采用继承的方式;添加到配置的方式参考 上文;

注意:投票器 vote 方法返回一个int值;-1代表反对,0代表弃权,1代表赞成;投票管理器收集投票结果,如果最终结果大于等于0则放行该请求。

  • 自定义token处理过滤器

自定义 token 处理器继承自 OncePerRequestFilter 或者 GenericFilterBean 或者 Filter 都可以,在这个处理器里面需要完成的逻辑是:获取请求里的 token,验证 token 是否合法然后填充 SecurityContextHolder ,虽然说过滤器只要添加在投票器之前就可以,但我这里还是建议添加在 http.addFilterAfter(new MyFittler(), LogoutFilter.class);

  • 登出成功处理器

实现LogoutSuccessHandler接口,添加到配置的方式参考上文。

  • 登录失败处理器

登录失败默认跳转到登录页,我们同样可以自定义。继承 SimpleUrlAuthenticationFailureHandler 或者实现 AuthenticationFailureHandler,建议采用继承。

  • 自定义UsernamePasswordAuthenticationFilter

我们自定义UsernamePasswordAuthenticationFilter可以极大提高我们 Security的灵活性(比如添加验证验证码是否正确的功能)。

我们直接继承 UsernamePasswordAuthenticationFilter ,然后在配置类中初始化这个过滤器,给这个过滤器添加登录失败处理器,登录成功处理器,登录管理器,登录请求 url 。

这里配置略微复杂,贴一下代码清单

初始化过滤器:

MyUsernamePasswordAuthenticationFilte getAuthenticationFilter(){

MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter = new MyUsernamePasswordAuthenticationFilter(redisService);

myUsernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(new MyUrlAuthenticationFailureHandler());

myUsernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(new MyAuthenticationSuccessHandler());

myUsernamePasswordAuthenticationFilter.setFilterProcessesUrl(“/sign_in”);

myUsernamePasswordAuthenticationFilter.setAuthenticationManager(getAuthenticationManager());

return myUsernamePasswordAuthenticationFilter;

}

添加到配置:

http.addFilterAt(getAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);

总结

==

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

看完上述知识点如果你深感Java基础不够扎实,或者刷题刷的不够、知识不全面

小编专门为你量身定制了一套<Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法>

image

针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺

image

全都是一丢一丢的收集整理纯手打出来的

更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~

image

image

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

[外链图片转存中…(img-jgUSVXMI-1712808972763)]

针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺

[外链图片转存中…(img-pOv63TQq-1712808972764)]

全都是一丢一丢的收集整理纯手打出来的

更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~

[外链图片转存中…(img-qmWHM4E3-1712808972764)]

[外链图片转存中…(img-qH1Ai90J-1712808972764)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-ylnquTlr-1712808972764)]

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值