Add Principal/authority dynamically for anonymous user - java

I am using spring security 2.x (+spring + struts2) and would like to enable add authority to user dynamically after user submits a form.
I have a protected directory (/protected/dir/) which is protected by ROLE_USER
<sec:intercept-url pattern="/protected/dir/**" access="ROLE_USER, ROLE_ADMIN" />
Which user can access after they login.
I want to make this accessible to the user who submitted the form (without logging in) by adding a temporary ROLE_TEMP to the principal (which may not even exist, since user hasn't been login, so I may have to add that too to the securityContext)
I have tried to access SecurityContext and add new Principal in my controller/action class. but I am unable to get SecurityContext. (I think SecurityContext only run on its own thread and you cannot pass it around, that's why I got NPE)
So what is the best way of doing this?
Please advise
Thanks

One way to support anonymous users is to add this filter:
/**
* Detects if there is no Authentication object in the SecurityContextHolder,
* and populates it with one if needed.
*/
org.springframework.security.providers.anonymous.AnonymousProcessingFilter
The filter has this attribute that will force the filter to remove the anonymous session after the request is complete:
public void setRemoveAfterRequest(boolean removeAfterRequest);

Related

Set Security Context within AuthenticationSuccessEvent Listener

I am working on a web application that uses Spring Security. We are using a legacy database system, so it was necessary to write a custom AuthenticationProvider. After successful authentication, we can load info on the user, e.g. roles, available domains, etc. While this logic can be contained within the AuthenticationProvider, we have good reasons to factor it out to an external location. To do so, I wrote a listener for the Spring Security AuthenticationSuccessEvent:
public void onApplicationEvent(AuthenticationSuccessEvent event) {
Authentication auth = event.getAuthentication();
User user = (User)auth.getPrincipal(); //Custom UserDetails implementation
List<GrantedAuthority> newAuthorities;
//Do stuff to user and get new authorities
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(user, null, newAuthorities);
}
The SecurityContext is changed within the method, but then I seem to lose the new authorities afterwards. In particular, within the method, the SecurityContext contains
UsernamePasswordAuthenticationToken#70df1ce8
At the end of the filter chain, I get the message that
UsernamePasswordAuthenticationToken#bbe0f021
is being persisted by SecurityContextPersistenceFilter.
I may be able to work around this by just putting the logic the AuthenticationProvider, customizing the Authentication Filter, or trying to use AuthenticationSuccessHandler instead. But I'd still like to understand why the changes made in the event handler aren't reflected outside of it.

Setting UserPrincipal in form based authentication

[JEE, MVC-JSP+Servlets, TomEE]
Using form based declarative authentication (container managed). Is it possible to explicitly set UserPrincipal? (to log some user in).
I know I can check whether there is logged in user or not with request.getUserPrincipal()!=null.
Actually I am facing following situation: I have a register.jsp that is being used for new users registration. So data from this jsp are sent to servlet where new user object is created and persisted to database. So, now when user has registered, he/she should be automatically logged in. So, I was thinking how can I implement this automatic login after registration.
If you are on Servlet 3.0 and above, use HttpServletRequest.login().

Java SpringSecurity automatic login with HTML GET parameters

I want to make an automatic login into web application, which will be accessible on company's intranet.
The login will function in a way that when user is accessing the application, he will automatically send its credentials (username and password), example (company.com/myapplication/login?user=jhon&pass=123).
How can I implement that instead standard Spring Security login using HTML forms? Maybe using hidden form which will be then filled with GET parameters? I can't find any examples for that scenario.
My part is only after user has sent the link with parameters.
You can do this is two ways (or more). (after our comment, it seams that you need to go with way two, because you do not have a username and password)
First way:
Use the standard spring form login and then modify you application so that is send login request like the normal web form login would do.
Assume you have configured the login-processing-url="/login/j_spring_security_check"
<security:form-login
login-processing-url="/login/j_spring_security_check"
login-page="/login"
authentication-failure-url="/login?login_error=t" />
then send a
HTTP POST to https://yourApplication/login/j_spring_security_check with the two POST parameters
j_username=<login>
j_password=<password>
Second way:
Write your own Authentication Processing filter. That is a class that extends AbstractAuthenticationProcessingFilter and it is responsible for
taking stuff that the user used to authenticate (normally username and password) from the request,
forming some the users authentication token object from them (for example an UsernamePasswordAuthenticationToken)
and invoking AuthenticationManager.authenticate(Authentication authentication) with this authentication token
To register your filter, you only need to add them to the spring security filter chain:
<security:custom-filter ref="yourFilter" after="FORM_LOGIN_FILTER"/>
I recommend to have a view on the UsernamePasswordAuthenticationFitler (and keep in mind that is extends AbstractAuthenticationProcessingFilter) - this will explain it best.
If you do not have an username and password, then you need to create your own token (extends Authentication) and then you have to implement your own AuthenticationProvider (and register with the AuthenticationManager). A AuthenticationProvider is reponsible to
- consume an (special type of) Authentication Token and
- validating that the stuff in the Authentication Token is valid
- creating an OTHER Authentication object with UserDetails and Privileges
- or, if the Authentication Token is not valid, throwing an AuthenticationException
Have a look at AbstractUserDetailsAuthenticationProvider and its subclass, for an example.

Spring + GWT project - execute handler on every user action

I'm new one in Spring, GWT and even Java World. So be patient. We have relatively big project, which one used Spring, GWT, Hibernate and Signal-Com Inter-Pro (Russian solution for html form signing to secure identified clients).
So now when user tried to log in into system, it read certificate s/n from http headers, compare with s/n from database. If they are equal, user can work with system. Otherwise, notify user and security administrator.
My current task is to add this check to every user action, i.e. GWT button click, switching to next view and so on. Is there a place where you can organize such a test?
TECH INFO:
Login form have redirect to special page
final FormPanel form = new FormPanel();
form.setAction(GWT.getModuleBaseURL() + "checkCertificate.htm");
Next, checkCertificate.htm have mapping in dispatcher-servlet.xml:
bean name="/base_dir/checkCertificate.htm" class="...CheckCertificateController">
property name="checkSignature" ref="checkSignature"/>
/bean
All necessary certificate actions are implemented in
public class CheckCertificateController extends AbstractController {
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
}
which is called when user click login button.
We have a Servlet Filter which performs a security check each time the user needs any information from the database.
Although that's not quite the same as performing a check with each user action, it works pretty effectively for us.
Alternatively you could set up a regular repeating command which would check at specific intervals and lock the user out if their serial number was invalid.

Spring - Call custom-authentication-provider from a controller

I have a custom-authentication-provider defined in my Spring Security configuration. This class implements AuthenticationProvider, and I can successfully log in using the form defined on my page. The issue is I want to call this class not just on the login page, but from the registration page as well.
The registration page uses a different command class and collects more information than the login form. Right now, when the user registers, I call the appropriate controller, add the record to the database and they can then log in but they aren't logged in automatically. As they've just given me their user name/password on the registration page, can I then pass this to the custom AuthenticationProvider class so they are also logged in?
I've tried creating an org.springframework.security.Authentication class in the registration controller and calling the authenticate method on my customer AuthenticationProvider class, and this doesn't error out, but the user isn't logged in. Do I have to call a method higher in the Spring Security filter chain to accomplish this? Should I redirect the controller to the j_spring_security_check URL? If so, how would I pass the username/password?
You need to put the result of AuthenticationProvider.authenticate() into SecurityContext (obtained from SecurityContextHolder).
Also be aware of AuthenticationSuccessEvent - if your application rely on this event (some Spring Security features may use it, too), you should publish it (you can obtain the default AuthenticationEventPublisher via autowiring). It may be useful to wrap your authentication provider with ProviderManager, it publishes the event automatically using the given publisher.
The problem you are having is that although you have successfully authenticated the user you have not stored the result of this authentication in the user's SecurityContext. In a web application this is a ThreadLocal object which the SecurityContextPersistenceFilter will use to store the user's credentials in the HTTPSession
You should also avoid authenticating directly with your custom authentication provider if you can. Your xml configuration should contain an AuthenticationManager which your custom authentication provider has been wired into. For example,
<bean id="customAuthenticationProvider"
class="com.foo.CustomAuthenticationProvider">
<property name="accountService" ref="accountService"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
If you wire the authenticationManager into your registration service and authenticate using that it will additionally,
allow you to swap in/out additional authentication providers at later points
publish the authentication result to other parts of the Spring Security framework (eg success/failure Exception handling code)
Our registration service does this as follows
final UsernamePasswordAuthenticationToken authRequest = new
UsernamePasswordAuthenticationToken(username, password);
final Authentication authentication =
authenticationManager.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
We also optionally store the authentication result at this point in a remember-me cookie using the onLoginSuccess() method of TokenBasedRememberMeServices.

Categories