春季安全手册登录最佳实践 [英] spring security manual login best practice

查看:120
本文介绍了春季安全手册登录最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using spring security to implement a programmatic, manual user login. I have a scenario where I have positively established the user's identity, and wish to log them in. I don't know their password, and so can't use the regular login code path where you submit a form to a url, which spring intercepts via a servlet Filter, doing all of it's auth+session magic.

我搜索了它,它似乎大多数人都会创建自己的身份验证对象,然后通过以下方式告诉spring:

I've searched, and it seems most people create their own Authentication object, and then tell spring about via:

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

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

Indeed, this works. Spring even puts it into the session for me, making subsequent http requests maintain their auth status.

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

However, I feel like this is a dirty hack. I'll present some details that I hope will give concrete examples of the problems associated with using setAuthentication() inside a controller to achieve a manual login:

为了给出一个想法,我的配置是:

To give an idea, my config is:

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)。 >
- 我想使用会话注册表

- ...更多,如果我选择配置它。

Key points in the above:
- I use custom success and failure handlers for the form login
- I want to config behavior for max concurrent sessions per user
- I want to maintain spring's default session fixation protection (changing session id upon login).
- I want to use a session registry
- ... more, had I chosen to config it.

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

I stepped through the code to see how spring processes a form login. As expected, Spring does everything that my HttpSecurity config told it to do when I use the form login. But, when I do my own custom/manual login via SecurityContextHolder.getContext().setAuthentication(), it does none of that. This is because spring does all of it's auth+session stuff inside of a servlet Filter, and my programmatic code can't really call a Filter. Now, I can attempt to add the missing behaviors myself, duplicating their code: I see that the Filter uses: ConcurrentSessionControlAuthenticationStrategy, ChangeSessionIdAuthenticationStrategy, and RegisterSessionAuthenticationStrategy. I can create these objects myself, configure them, and call them after my custom login. But, that's kinda lame to duplicate it in that fashion. Furthermore, there's still other behaviors I'm missing - I noticed that when using the form login code path, that spring triggers some login events which don't get triggered when I do my custom login. And there's probably other stuff that I'm missing or don't understand. The whole process is pretty complicated.

所以,我觉得我正在以错误的方式接近这个。 我是否应该使用不同的策略,以便我不会绕过春天为我做的那么多东西?也许我应该尝试制作自己的 AuthenticationProvider 完成此自定义登录?

So, I feel like I'm approaching this from the wrong way. Should I be using a different strategy, so that I'm not bypassing so much of the stuff that spring does for me? Maybe I should try to make my own AuthenticationProvider to accomplish this custom login?

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

*To clarify, my code more or less works. But, I feel like I accomplished it using a poor strategy because I had to write code duplicating a lot of stuff that spring does for me. Further, my code doesn't perfectly replicate what spring does, making me wonder what negative implications might result. There must be a better way to programatically achieve login.

推荐答案

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

For custom web authentication you should implement combination of a custom authentication filter (for example AbstractAuthenticationProcessingFilter or just GenericFilterBean), a custom authentication provider (AuthenticationProvider) or/and custom authentication token (AbstractAuthenticationToken).

例如,参见 Spring Security Kerberos

参见:


  • < a href =https://docs.spring.io/spring-security/site/docs/current/reference/html/core-services.html#core-services-authentication-manager =nofollow noreferrer> AuthenticationManager,ProviderManager和AuthenticationProvider

  • The AuthenticationManager, ProviderManager and AuthenticationProvider

这篇关于春季安全手册登录最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆