春季安全手册登录最佳实践

时间:2017-11-11 00:44:35

标签: java spring spring-security

我正在使用spring security来实现程序化的手动用户登录。我有一个场景,我已经积极建立用户的身份,并希望登录。我不知道他们的密码,所以不能使用常规登录代码路径,你提交表单到网址,春天通过servlet Filter拦截,完成所有的auth +会话魔法。

我已经搜索过,似乎大多数人都会创建自己的Authentication对象,然后通过以下方式告诉spring:

PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(user, "", user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);

确实,这很有效。 Spring甚至将它放入会话中,使后续的http请求保持其身份验证状态。

然而,我觉得这是一个肮脏的黑客。我将提供一些细节,希望能给出在控制器中使用setAuthentication()来实现手动登录的相关问题的具体示例:

要提出一个想法,我的配置是:

httpSecurity
    .authorizeRequests()
    .antMatchers("/test/**").permitAll()
    .antMatchers("/admin/**", "/api/admin/**").hasRole("USER_SUPER_ADMIN")
    .and()
    .formLogin()
    .loginPage("/sign-in?sp")
    .loginProcessingUrl("/api/auth/sign-in")
    .successHandler(createLoginSuccessHandler())
    .failureHandler(createLoginFailureHandler())
    .permitAll()
    .and()
    .logout()
    .logoutUrl("/api/auth/sign-out")
    .logoutSuccessHandler(createLogoutSuccessHandler())
    .and()
    .sessionManagement()
    .maximumSessions(1)
    .maxSessionsPreventsLogin(true)
    .sessionRegistry(sessionRegistry)
;

以上要点:
  - 我使用自定义成功和失败处理程序进行表单登录
  - 我想为每个用户的最大并发会话配置行为
  - 我想保持spring的默认会话固定保护(登录时更改会话ID)   - 我想使用会话注册表
  - ...更多,如果我选择配置它。

我逐步完成了代码,看看spring如何处理表单登录。正如预期的那样,当我使用表单登录时,Spring会执行我的HttpSecurity配置要求它执行的所有操作。但是,当我通过SecurityContextHolder.getContext().setAuthentication()进行我自己的自定义/手动登录时,它没有做到这一点。这是因为spring在servlet Filter中完成了所有的auth + session事务,而我的编程代码实际上无法调用Filter。现在,我可以尝试自己添加丢失的行为,复制他们的代码:我看到过滤器使用:ConcurrentSessionControlAuthenticationStrategyChangeSessionIdAuthenticationStrategyRegisterSessionAuthenticationStrategy。我可以自己创建这些对象,配置它们,并在我的自定义登录后调用它们。但是,以这种方式复制它有点蹩脚。此外,我还缺少其他行为 - 我注意到当使用表单登录代码路径时,该弹簧会触发一些登录事件,这些事件在我进行自定义登录时不会被触发。而且可能还有其他我缺少或不理解的东西。整个过程非常复杂。

所以,我觉得我是从错误的方式接近这个。 我是否应该使用不同的策略,以便我不会绕过春天为我做的那么多东西?也许我应该尝试自己AuthenticationProvider来完成这个习惯登录资讯?

*为了澄清,我的代码或多或少有效。但是,我觉得我是用一种糟糕的策略来完成它的,因为我必须编写代码来复制很多春天给我的东西。此外,我的代码并没有完全复制Spring的功能,让我想知道可能会产生什么负面影响。必须有一种更好的方式来以编程方式实现登录。

1 个答案:

答案 0 :(得分:1)

对于自定义Web身份验证,您应该实现自定义身份验证筛选器(例如AbstractAuthenticationProcessingFilter或仅GenericFilterBean),自定义身份验证提供程序(AuthenticationProvider)或/和自定义身份验证令牌的组合(AbstractAuthenticationToken)。

例如,请参阅Spring Security Kerberos的来源。

另见: