Spring Request Mapping call one Function to check User - java

I have different mappings that start with \mobile or contain \mobile. Is there a way to catch all these mappings?
My Mappings are:
\mobile\login.mvc
\mobile\profile\details.mvc
\secure\mobile\profile\edit.mvc
Now I want that for all "\mobile" mappings one function oder mapping is called, and then the call mapping.
Background: I want to check with every call, whether the user is logged in and sign him if necessary. But I would not query at every mapping the parameters username and password but all in one place.

If you want to authenticate user in every controller then Spring AOP will be a good choice.
You can write a single authentication method and invoke it before controller using AOP.
This might help http://tedone.typepad.com/blog/2011/05/using-aop-easily-with-aspectj-and-spring.html

Related

Spring Boot authorisation in services

I have a Spring Boot application which uses Spring Security to Authenticate and Authorise requests using a JWT. However, some requests should only be able to be executed by a particular user. For example:
GET /users/{id}/orders should only return the list of orders if {id} is the current user or the current user is ADMIN
PUT /orders/{id} should only edit the order if the its payer is the current user
PUT /representation-requests/{id}/accept should only work if the current user is the target of the representation request
Because of the usage of JWTs, the way I get the current user's ID is by
String userId = ((DecodedJWT) SecurityContextHolder.getContext().getAuthentication().getDetails()).getSubject();
I've implemented this in the various methods of the services responsible for handling each API call. My question is if there is a more general way to do this using Spring Boot and Spring Security? Or is this not a standard use case?
I have looked at #PreAuthorize annotation in controllers, but it does not suite my needs as the URL parameters are not enough to check the nested entities. #PostAuthorize in controllers seems closer, but because of the JWT I couldn't get it to work (and it also seems a bit clunky to do long code in annotations, not sure it is better than doing it in the service itself). I appreciate a pointer in the right direction.
You'll have to play around with it a bit (I can't give you 100% specifics for JWT), but you basically could use SpEL to achieve what you want. (I'm unsure why you think #PostAuthorize could be a better fit, though)
Either like so, for simple checks (# denotes a method parameter)
#PreAuthorize("principal?.id == #id")
public List<Order> ordersForUsers(Integer id) {
// do someting
}
Or like so, delegating to a custom bean (# denotes a bean name, hash the method param, 'admin' the role you want, or any other parameter, really)
#PreAuthorize("#yourBean.hasPermission(principal, #id, 'admin')")
public List<Order> ordersForUsers(Integer id) {
// do someting
}

REST service to return only current user-related resources

I have a REST service implemented using Spring MVC (RestControllers) with token based security (using Spring Security). How can i filter resources depending on user identity? Let's say user has some reports. How can I let authorized user by performing a call to /reports to see only his reports?
Obviously i can make userId to be a request parameter or path variable, but something tells me that this is a bad practice.
I assume i can achieve that using Spring Security features, but how exactly could i do that and, more important, where is the most appropriate place to apply such filtering? Should controllers perform calls to services passing user identity or should it be somehow retrieved at repositories level (I use Spring Data JPA)?
Thanks in advance
You have Authentication object whenever a user is successfully logged in.
It contains Object principal Object credentials and Set authorities.
All you need to do is override UserDetailsService to add new parameters for your authenticated user. Add your userId in authentication as shown in blog
Now when you do
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
this will return you the User object of the spring security.
You can get the user id from here and use this in controller to do necessary actions.

User data carriage using Interceptors in Struts2

I am using Struts2 framework to implement the MVC architecture in my Web application. While allowing the user to obtain an ID-specific session, I need to take the username and password from a JSP form. Instead of passing this data to the Action class directly, I want to check the validity of the values in an Interceptor and then check or continue the flow depending on business logic-specific criteria.
Hence, my quest is to obtain the user data from the JSP form in the Interceptor. What is (if there's any) way to do that?
Thanks in advance!
If you are validating the username and password through a call to a DB or another service,it would be better to have a separate action for it.
However subsequent calls to business logic can be prehandled via the request context in the interceptor itself.

How to ensure the user is logged into the system at the controller level?

I'm using spring MVC, and I have a custom authentication/security system that I had to build.
NOTE: I know of spring security, but my requirements were to do this in a custom way so please not looking for suggestions about using spring's security modules.
When the user logs into the system, it creates a session cookie. When the user visits a page, a interceptor looks for the existance of that cookie, and looks up the session guid in mysql and if it is present that it loads some data and stores it in the request's attributes.
Now for pages where the user has to be logged in, how can I restrict access at the controller level?
I could do this in an interceptor:
if url.contains("projects/") ...
If I want to restrict access to only logged in users in the ProjectController, but this isn't really something I want to do.
But I am looking for maybe a annotation I could add at the controller level, or maybe somehow create a BaseController that all controllers that require a loggedin user will inherit from.
What are my options for something like this?
In ASP.NET, I created a baseController, and the controller has an event cycle, and in the before-action fired event I checked to see if the user was logged in.
So looking for suggestions for spring mvc?
Update
For example, in ASP.NET you have 2 methods, 1 that fires just before the controller's action method and one that fires after:
Controller.OnActionExecuting
Controller.OnActionExecuted
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting.aspx
So in the OnActionExecuting, I can actually see exactly which controller I am in, and which action is about to get called in a programatic way, not by looking at the request URL and then doing string compares to see if it is a particular controller etc.
So in this event, I can simply check for things in cookies or in my request attributes etc.
This is a much more stable way to do it, does spring have anything similiar?
If you need this at the controller level, you could:
1) declare a java.security.Principal parameter in the controller method signature, which Spring will fill in with a Principal object, or
2) implement a PermissionEvaluator, which can be called on a controller method using the #PreAuthorize annotation, and which would have access to a Authentication object.
Similar to what you did in ASP.NET, you can take advantage of OncePerRequestFilter and chain it to the chain of filters you have in web.xml or Spring application context. The good point about this filter is that it's independent of the MVC approach that you take and no need for a "base controller".
On the other hand, if you're also using Spring security module, you can use a custom filter configuration and place it in the correct place that it should be.
If the check fails, then you'd probably want to raise exceptions or redirect user to the correct navigation.
Based on the last comment, you can also use mapped interceptors:
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/myFirstPath/*"/>
<mapping path="/mySecondPath/*"/>
<bean class="org.example.SomeInteceptor" />
</mvc:interceptor>
<mvc:interceptor>another one</mvc:interceptor>
</mvc:interceptors>

Passing variables to a POST request from an outside controller

Since you guys have been very helpful in my early steps into the Play Framework (thanks for that), here it goes again:
We have a working registration controller, that POSTS all credentials to the database.
But then, we want to make it possible to be immeadiately logged in afterwards. Below is the code that makes this work:
public static void doRegistration(#Valid User user) {
//registering the user
try{
SecureController.authenticate(user.username, user.password, false, "MainController.index");
}catch(Throwable ex){
MainController.index();
}
This works fine, but it is not very safe because it GETs all the credentials to the server. I know I have to edit my routes file somehow, but I can't see how.
The routes file:
* /account SecureController.login
POST /account/register RegistrationController.doRegistration
GET /account/register SecureController.login
Somewhere should be the action SecureController.authenticate, but what do I have to put in the column after the POST... It can't be /account/register, because that fails...
Thank you beforehand!
I am not sure I understand your issue. The routes file is just a way to configure your URLs to be pretty URLs. If you don't specify them, then it falls back on default {controller}/{method} syntax.
The issue you are having, is that when you call another controller Play performs a redirect to that controller's method, which involves sending a request back to your browser telling it to redirect (this ensures that the state of the application is reflected in the URL within the browser). A redirect needs therefore to send a GET request, and included in the GET request will be your parameters.
what you are trying to do, as you said, is not safe. What you should do (not the only option, only one possibility) is:
Maintain your current doRegistration action for the user
Create a service class (that does not inherit Controller). It can be static or require instantiation (with static methods should be enough though).
Add a #Before method to a common controller that will be executed always. One way is to create a controller with a #Before method and add this controller to all other controllers via the #With annotation, so that #Before will be executed always for all controllers. It requires you to add a #With to each new controller, but I believe it keeps the code quite clean.
The idea would be that the controller calls the authenticate method from the service class. It's a simple static This method checks the user (if it's enabled, has proper license, whatever) and sets some parameters in the session (via Session object).
To help with this you may want to create another authenticate method in the user that returns the attributes to set (for example in a Map, if it contains an "error" key the user can't be authenticated for some reason). How to do this step can change according to your requirements.
Once the Session has been set, you redirect to the page of your election (main, profile, etc). As you have the common #Before method, this will be executed. This method should verify the credentials in the session (user authenticated, license type, etc) and act accordingly. You have an example in the Secure controller of Play, but you could create your own.
With this, you could user the authenticate method of the service from any controller, allowing authentication via multiple methods, and using a common point to verify the session.

Categories