Java Spring-Security:认证后调用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2579431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring-Security: Call method after authentication
提问by UmYeah
I'd like to track when users are logging in to my application. I have some code that I would like to execute right after the user is authenticated. The problem is, I can't figure out where this should be called. Does spring-security have a way to call a method after authentication?
我想跟踪用户何时登录我的应用程序。我有一些代码希望在用户通过身份验证后立即执行。问题是,我不知道应该在哪里调用它。spring-security 是否有认证后调用方法的方法?
回答by Gandalf
Just write your own SpringSecurityFilter and add it to the filter chain right after your authentication provider is called.
只需编写您自己的 SpringSecurityFilter 并在您的身份验证提供程序被调用后立即将其添加到过滤器链中。
package my.code;
public class AuditFilter extends SpringSecurityFilter {
public void doFilterHttp(...) throws ... {
{application code to run before request is processed}
chain.doFilter(...);
{application code to run after request has fully processed}
}
}
Then in your configuration XML (wherever you setup the Security Filter chain) add a line like this:
然后在您的配置 XML(无论您在何处设置安全过滤器链)中添加如下一行:
<bean id="auditFilter" class="my.code.AuditFilter>
<security:custom-filter position="LAST"/> <-- you can change the position
</bean>
回答by manishpal
This link Post Authentication Logicon ByteClip explains how to execute some logic after successful authentication without disturbing spring security filter chain
这个链接ByteClip 上的Post Authentication Logic解释了如何在成功认证后执行一些逻辑而不干扰 spring 安全过滤器链
回答by ams
Best way is to create an application listener and register it with the spring security context.
最好的方法是创建一个应用程序侦听器并将其注册到 spring 安全上下文。
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
public class AuthenticationSuccessListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
@Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
System.out.println("User Logged In");
}
}
Make sure to add the above class the spring-security.xml as a bean. There are lots of other types of security events listeners you can listen to, check the type hierarchy for a list of all the types of security events you can listen to.
确保将上述类添加到 spring-security.xml 作为 bean。您可以侦听许多其他类型的安全事件侦听器,请检查类型层次结构以获取您可以侦听的所有类型的安全事件的列表。
回答by sab
probably will be usefull for someone... In case of Spring 3, configure security:
可能对某人有用......在Spring 3的情况下,配置安全性:
<security:http use-expressions="true" auto-config="true">
<security:intercept-url pattern="..."/>
<security:form-login
authentication-failure-handler-ref="authFailureHandler"
authentication-success-handler-ref="authSuccessHandler"/>
<security:logout success-handler-ref="logoutSuccessHandler"
invalidate-session="true"/>
<security:session-management session-fixation-protection="newSession"/>
</security:http>
<bean id="authFailureHandler" class="mine.AuthenticationFailureHandlerImpl"/>
<bean id="authSuccessHandler" class="mine.AuthenticationSuccessHandlerImpl"/>
<bean id="logoutSuccessHandler" class="mine.LogoutSuccessHandlerImpl"/>
and implement an appropriate class:
并实现一个适当的类:
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//do what you want with
response.getOutputStream().write("success".getBytes());
}
}
You can link resources via that xml config.
您可以通过该 xml 配置链接资源。
回答by Lee Chee Kiam
In case you want to continue with default behavior but just in between perform your own business logic, you may extend SimpleUrlAuthenticationSuccessHandler
and invoke super.onAuthenticationSuccess(request, response, authentication);
before you return. More details refer to https://stackoverflow.com/a/6770785/418439
如果您想继续使用默认行为,但只是在执行您自己的业务逻辑之间,您可以在返回之前extend SimpleUrlAuthenticationSuccessHandler
调用super.onAuthenticationSuccess(request, response, authentication);
。更多详情请参考https://stackoverflow.com/a/6770785/418439
回答by user455495
Authentication does notnecessarily imply successful login. A user can be successfully authenticated via, e.g., two-way SSL (X.509 certs), and still Spring Security will redirect you to an error page if session concurrency management is set up with max-sessions="1"
and this is a second concurrent login attempt. If your setup is simple, without session concurrency control, you can assume login = authentication for all practical purposes. Otherwise, if you have, e.g., logic that records every successfullogin in a database, you will have to invoke this logic at the point of actuallogin, not at the point of authentication. One way (by no means optimal, subject to my limited understanding of the Spring Security framework) to do this is to implement your own ConcurrentSessionControlAuthenticationStrategy
(click herefor the source code) and inject it into CompositeSessionAuthenticationStrategy
in your Spring Security (3.2 and above) configuration XML:
验证并没有一定意味着成功登录。用户可以通过例如双向 SSL(X.509 证书)成功验证,如果设置了会话并发管理,Spring Security 仍会将您重定向到错误页面max-sessions="1"
,这是第二次并发登录尝试。如果您的设置很简单,没有会话并发控制,您可以假设 login = authentication 用于所有实际目的。否则,如果您有,例如,在数据库中记录每次成功登录的逻辑,您将必须在实际登录时调用此逻辑,而不是在身份验证时。一种方法(绝不是最佳的,受限于我对 Spring Security 框架的有限理解)是实现你自己的ConcurrentSessionControlAuthenticationStrategy
(单击此处获取源代码)并将其注入到CompositeSessionAuthenticationStrategy
您的 Spring Security(3.2 及更高版本)配置 XML 中:
<http>
.
.
<session-management session-authentication-strategy-ref="sas" />
.
.
</http>
.
.
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean class="path.to.my.implementation.of.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1"/>
<beans:property name="exceptionIfMaximumExceeded" value="true"/>
<beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>
<beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"/>
<beans:constructor-arg ref="sessionRegistry"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
I would have preferred to inject a custom PostLogin
handler into the framework's ConcurrentSessionControlAuthenticationStrategy
, instead of copy-pasting from it into my custom ConcurrentSessionControlAuthenticationStrategy
and making modifications to it, but I do not know of a way to do this at the moment.
我宁愿将自定义PostLogin
处理程序注入框架的ConcurrentSessionControlAuthenticationStrategy
,而不是将其复制粘贴到我的自定义中ConcurrentSessionControlAuthenticationStrategy
并对其进行修改,但我目前不知道有什么方法可以做到这一点。
A more complete configuration example can be found here.
可以在此处找到更完整的配置示例。
回答by gjambet
If you want to avoid reading all the thread : curated version with annotations & a bit more explanatory :
如果你想避免阅读所有线程:带有注释的策划版本和更多解释:
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
@Component
public class LoginSuccessListener implements ApplicationListener<AuthenticationSuccessEvent{
@Override
public void onApplicationEvent(AuthenticationSuccessEvent evt) {
// if you just need the login
String login = evt.getAuthentication().getName();
System.out.println(login + " has just logged in");
// if you need to access full user (ie only roles are interesting -- the rest is already verified as login is successful)
User user = (User) evt.getAuthentication().getPrincipal();
System.out.println(user.getUsername() + " has just logged in");
}
}