We use RequestHeaderAuthenticationFilter
as to implement pre-authentication strategy and PreAuthenticatedAuthenticationProvider
as the authentication provider. One of the requirements is to store all successful logins to the database with following information. As user IP address and other request related info is not available in UserDetailsService
class, what is the best strategy to retrieve this info and store in db?
The HttpServletRequest.getUserPrincipal() will return the result of SecurityContextHolder.getContext().getAuthentication() . This means it is an Authentication which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication.
In order to get the current username, you first need a SecurityContext , which is obtained from the SecurityContextHolder . This SecurityContext kepy the user details in an Authentication object, which can be obtained by calling the getAuthentication() method.
Basically and() method is used to concatenate multiple configurer of Spring Security You can refer attached image to understand more clearly.
All the information is available through HttpServletRequest
. You can obtain it by:
The easiest way would be to inject servlet request directly into your UserDetailsService:
class:
public MyDetailsService implements UserDetailsService { @Autowired private HttpServletRequest request; //... }
(as suggested by OP) Remember to add the following listener to your web.xml
:
<listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener>
UPDATE: This works because Spring injects special scoped proxy implementing HttpServletRequest
, so you are able to access request-scoped request "bean" from singleton-scoped MyDetailsService
. Under the hood every call to request
's parameters is routed to org.springframework.web.context.request.RequestContextHolder#requestAttributesHolder
ThreadLocal
which you can also access directly. As you can see Spring is very flexible when it comes to scoping rules. It just works.
RequestContextHolder
Another approach is to use RequestContextHolder
:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder. currentRequestAttributes()). getRequest();
This might be a good approach:
1) Create a class that extends SavedRequestAwareAuthenticationSuccessHandler
public class MyCustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
2) Assign the "success handler" to your security filter:
<beans:bean id="myFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="failureHandler" />
<beans:property name="authenticationSuccessHandler" ref="successHandler" />
</beans:bean>
<beans:bean id="successHandler" class="yourPackage.MyCustomSuccessHandler" >
<beans:property name="defaultTargetUrl" value="/index.html" />
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With