Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security - retrieve user IP, browser info and requested page

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?

like image 854
RKodakandla Avatar asked Oct 20 '11 16:10

RKodakandla


People also ask

What is SecurityContextHolder getContext () getAuthentication () getPrincipal ()?

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.

How do you retrieve the authentication user from the SecurityContextHolder?

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.

What is and () in Spring Security?

Basically and() method is used to concatenate multiple configurer of Spring Security You can refer attached image to understand more clearly.


2 Answers

All the information is available through HttpServletRequest. You can obtain it by:

Dependency injection

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(); 

Further reading:

  • Creating a Spring bean holds ServletRequest properties
  • Spring: how do I inject an HttpServletRequest into a request-scoped bean?
like image 154
Tomasz Nurkiewicz Avatar answered Oct 07 '22 03:10

Tomasz Nurkiewicz


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>
like image 30
Dani Cricco Avatar answered Oct 07 '22 03:10

Dani Cricco