背景
如题,由于业务需要,需要同时支持SSO登陆和账密登陆两种方式,本来单独使用SSO或单独账密登陆都无问题,但是两个同时使用的话,常规方法是提供两个authenticationProvider,分别按情况进行认证即可。
出现的问题是,设置之后账密登陆正常,SSO登陆总会在CAS验证服务完成返回ticket后,被后端服务拦截提示401,研究了很久也没有找到问题的原因,推测是账密登陆的provider的某些默认配置覆盖了casprovider的一些路由规则,导致拦截,但没有找到设置方法,因时间有限没有再进行深究,查看了Spring Security的官方文档,也算是有所收获,所以在此记录一下。当然问题也要解决,最终采用了默认的账密认证加一个casprovider的方式达到了想要的效果。
过程记录
- 对于Spring Security 的整体认识,主要都在官方文档上,各个类的概念、关系都很清楚,如果以后使用直接参看即可,Spring相关的学习看来以后都可以看官方文档,忘了也没关系 docs.spring.io/spring-secu…
- 探索过调整两个provider的加入顺序,没有效果;同时也调整过对应的filter的顺序,同样是开头写的401的问题,所以问题可能不在这
- 也通过打断点看了变量的变化,发现两个provider加入都是正常的,而且顺序也是自己书写的顺序,所以排除了provider配置的相关问题,更加倾向于是配置覆盖的问题,虽然没有解决,但是使用打断点的方法也是不错的查找问题的方法,不止可以用在业务调试上,也可用于查看源代码的启动
- 在使用了auth.authenticationProvider(casAuthenticationProvider())函数之后,只要配置类中存在
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider{...}
即只要使用@Bean进行注入之后就会产生上述的401错误,这个还没有理解为什么,从现象看,注入之后spring框架就可以自动找到provider的配置,从而生效,而不必等到调用auth.authenticationProvider(daoAuthenticationProvider())之后才生效,auth.authenticationProvider()只是将provider加入到providers列表中,以便以后依次进行验证,没有调用就产生了401说明并不是加入providers列表才产生的影响 5. 最后看了这篇博文解决了问题 blog.csdn.net/xue31737891… ,其中有一个不起眼的函数,注销掉就解决了我的问题
if (casProperties.isCasEnable()) {
// super.configure(auth); //效果是使用默认的AuthenticationManagerBuilder配置,也就是如果这行不注掉的话,配置的provider信息是不能正常生效的,它使用的还是默认的配置
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
auth.authenticationProvider(casAuthenticationProvider());
// auth.authenticationProvider(daoAuthenticationProvider());
}
- 顺势研究了一下super.configure(auth)相关的用法,从 wch853.github.io/posts/secur… 这篇博文中发现,super.configure(auth)的确切效果就是,使用默认的AuthenticationManagerBuilder配置,如果想要使用自定义的(开发者干预过的配置),则不能添加这一行,至此,问题已经全部解决了,即使添加两个providers,只要不写super.configure(auth),就都能正常生效了
if (casProperties.isCasEnable()) {
// super.configure(auth);
// auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
auth.authenticationProvider(casAuthenticationProvider());
auth.authenticationProvider(daoAuthenticationProvider());
}
总结
- 遇到难解问题注意先从官方文档宏观了解架构和组件间的关系,一些博主的源码分析也很清晰明了
- super.configure(auth),一般情况下就不要加了