Spring Security 同时提供SSO登陆和账密方式登陆问题解决记录

50 阅读3分钟

背景

如题,由于业务需要,需要同时支持SSO登陆和账密登陆两种方式,本来单独使用SSO或单独账密登陆都无问题,但是两个同时使用的话,常规方法是提供两个authenticationProvider,分别按情况进行认证即可。
出现的问题是,设置之后账密登陆正常,SSO登陆总会在CAS验证服务完成返回ticket后,被后端服务拦截提示401,研究了很久也没有找到问题的原因,推测是账密登陆的provider的某些默认配置覆盖了casprovider的一些路由规则,导致拦截,但没有找到设置方法,因时间有限没有再进行深究,查看了Spring Security的官方文档,也算是有所收获,所以在此记录一下。当然问题也要解决,最终采用了默认的账密认证加一个casprovider的方式达到了想要的效果。

过程记录

  1. 对于Spring Security 的整体认识,主要都在官方文档上,各个类的概念、关系都很清楚,如果以后使用直接参看即可,Spring相关的学习看来以后都可以看官方文档,忘了也没关系 docs.spring.io/spring-secu…
  2. 探索过调整两个provider的加入顺序,没有效果;同时也调整过对应的filter的顺序,同样是开头写的401的问题,所以问题可能不在这
  3. 也通过打断点看了变量的变化,发现两个provider加入都是正常的,而且顺序也是自己书写的顺序,所以排除了provider配置的相关问题,更加倾向于是配置覆盖的问题,虽然没有解决,但是使用打断点的方法也是不错的查找问题的方法,不止可以用在业务调试上,也可用于查看源代码的启动
  4. 在使用了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());
        }
  1. 顺势研究了一下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());
}

总结

  1. 遇到难解问题注意先从官方文档宏观了解架构和组件间的关系,一些博主的源码分析也很清晰明了
  2. super.configure(auth),一般情况下就不要加了