I am using my own MVC implementation and I am not sure, whether the Spring Security isn't designed specifically for the Spring MVC implementation. Is it still okay to use it?
It is not clear to me, which parts of Spring Security I should use and which I don't need to. I suppose I don't need the URL filters as I need to validate the access specifically on the URL parameters in my controllers (for instance to check whether User is the owner of the Article). Something like:
if (request.getUser().isAllowedTo("EditArticle", 27)) {...}
if (request.getUser().isAllowedTo("CategoryManager", 123)) {...}
if (request.getUser().isInRole("Admin")) {...}
I could not find some clear way of users logging in/out programmatically. I've implemented my UserDetails and UserDetailsService classes to handle the users with JPA, but I don't see a way, how I can proceed with login and logout in my controllers.
EDIT:
I don't see a way how to put the <form> in my Freemarker templates - the only way of creating the form I found is with:
<http pattern="/login.htm*" security="none"/>
<form-login login-page="/login.htm" default-target-url="/home.htm"/>
</http>
How can I configure the structure of the login form? Can I create it by myself?
What I would like the most is to be able to handle the login by myself (for example with DWR) and not to use the magic j_security_checks...
It would be great, if I could handle the login request by myself and ask the auth service to login the user by myself (so I could easily use Direct Web Remoting (DWR)):
if (user.username.ok() and user.password.ok()) {
authService.setUser(user);
authService.setLoggedIn(true);
}
Spring security is not limited to spring mvc and can be used with your own framework implementation. It provides handy services for authentication and session management.
Spring is very convenient to use to leverage access by certain URLs but not limited to. You will be able to get which roles the current user has at the moment from the spring context and all the custom info you would include in your UserDetails object. There are number of ways to restrict access to certain actions by certain roles. However the code like if (request.getUser().isAllowedTo("EditArticle", 27)) {...} I think it will be simplier to check by yourself.
Login and logout are done by calling specific urls. For login: /j_spring_security_check. For logout: /j_spring_security_logout.
Related
I am trying to understand if there is a way to use spring security which helps my used case. Basically, I want to call spring security on each REST call in spring boot, rather than one time during the start of the application, and find the role of the user and further restrict endpoints based on the user roles.
I have 3 different rest controllers namely /admin1/*, /admin2/*, /admin3/*.
I have tried restricting endpoints manually as below.
http.authorizeRequests()
.antMatchers("/admin1/**").permitAll()
.and()
.authorizeRequests()
.antMatchers("/admin2/**").permitAll()
.anyRequest().authenticated();
This will actually allow /admin1/* and /admin2/* APIs to work and restrict /admin3/*. However, my used case is as below.
In each rest call, we pass the user id in the header. I would like to use spring security on each rest call, and use the user id from the header to find the user roles from the database.
If user has ADMIN 1 user role, we have to just enable /admin1/* endpoints and restrict /admin2/* and /admin3/*. Similarly, if user has ADMIN 2 user role, we have to just enable /admin2/* endpoints and restrict /admin1/* and /admin3/*. In the same way, if user has ADMIN 3 user role, we have to just enable /admin3/* endpoints and restrict /admin1/* and /admin2/*.
Is there a way to achieve this using spring security?
Thank you
AS far as I understood, you want to authenticate & authorize users on each call. True?
one way is tokenizing your REST APIs with JWT (JSON Web Token).
The example in https://dzone.com/articles/spring-boot-security-json-web-tokenjwt-hello-world would probably help.
I Also suggest that instead of using antMatchers In configure method to restrict URL access based on Roles, you use #PreAuthorize and #PostAuthorize annotations above the classes or methods you want to secure. This way gives you more flexibility on your restriction policies.
The example in https://www.baeldung.com/spring-security-method-security also may help you with that.
I would like to ask if there is a point to secure the methods which I call in a REST Controller with Pre and Post annotations. I have configured a security through java configuration like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.and()
.formLogin()
(...)
.and()
.authorizeRequests()
.antMatchers("/api/**").hasAuthority("ROLE_USER");
}
So every request under /api should be authorized with ROLE_USER. I tried to find some information about this in the internet but the only thing i could find was this:
https://coderanch.com/t/549265/Spring/method-security-spring-security
However I really can't think of a use case where a hacker would access somehow the methods in the service layer.
URL security and method security in service layer aims at different use cases.
If all you need is control that only users with a certain role can call URL with a given prefix (here API) URL security is what you need full stop.
If you have a complex application where some service methods can be called from different controllers and you want to make sure that you did not fail to restrict an access, method security can come to help by ensuring that only valid users can do certain business actions.
If you have a complex security model, for example several officse with one manager in each that has read and/or write access to his own employees data, method security on service layer directly using business model objects is the way to go.
BTW, using method security in a controller or even worse on a rest controller is generally design smell: if you can do it inside a controller it is generally better to use URL security. If it seems to make sense, you probably have imported business logic into a Fat Ugly Controller. Not speaking about method security being implemented with Spring AOP using by default JDK proxies, when controllers generally do not implement interfaces.
In addition to making it possible to have some kinds of functionality, using both techniques gives an additional layer of security.
Method level security is used to authorize the user. Spring security performs two basic operations before allowing the access.
Authenticate (Who is the user)
Authorize (What authorities the user has)
so for example if the user is having an authority of ROLE_USER and later in the architecture you decide to have rights assigned to some of the roles.
for example let's consider a role 'ROLE_USER'
and following rights has been assigned to the USER
CAN_VIEW_DATA
CAN_ADD_SUB_USERS
and so on.
so when some of the users have the right of CAN_ADD_SUB_USERS and some dont, then the method level security comes in handy.
Of course you have to play with the spring configurations for the rights and authority. But Once configured it provides an extra level of security that the applicaton might need.
Refer to this link for more info http://www.baeldung.com/role-and-privilege-for-spring-security-registration
REST is stateless. You should send something like access token (like Google API) with every request:
https://{server}/api/customers?access_token=BGhznFGDS
You can also send this information via Header-Attribute. The validation layer (Filter) decides whether the controller method may be called or not.
I prefer to implement my own Filters to get 100% of control.
I am studying for the Spring Core certification and I have some dobut related the meaning of this Spring Security diagram finding into the documentation:
It explain what is the architecture of the Spring Security projects and the interaction between its components but what exactly mean?
It show an Authentication Manager component, reading on the documentation I found that it handles authentication requests from other parts of the framework so I think that it provide something like an interface with some methods to perform the autherntication operations and that this interface it will be implemented by a specific authentitication providerd (according to the authentication technology choose)
What means that the Authentication Manager populates the Security Context. What exactly is the *Security Context** in Spring? Is it a "place" where are stored the information related to the Principal (for example an user authenticated on a web application) and the list of the authorizations of this principal on the secured resources? (for example the logged user and what operations this user can perform on the secured resources?) Is it right or am I missing something?
Then there is a Security Interceptor that I think have to be a proxied class that use something like a before advice AOP mechanism that perform a security advice befeore some specific joint point. Thee jointpoint are the operations on the secured resource (for example the method execution on a secured bean).
Looking at the picture I think that the proxy obtain this information from the Security Context that contains the principal (the logged user) and its authorizations (what operations can do this logged user) so it can create the before advices to check this operations. Is it right or am I missing something?
What represents the AccessDecision Manager component? and what are the voters showed into the picture?
Tnx
The security-context contains the security information about the current user (name, login, privileges...). It is bounded to the current thread and session https://stackoverflow.com/a/6408377/280244
The Authentication Manger will put ( poulate ) the security information about the user when he login into the security context.
The Security interceptor (Method or Http Request) will intercept the invocations before they invoke an protected/secured resource. It obtain the information about the current user from the security context. What the requies rules to allow the invocation are, are obtained form some configuration (xml, annotations, ...). The decision about that the current user matches the required rules are delegated to the Access Decision Manger
The Access Decision Manger does not implements the desision rules by its own, instead it uses (different) Voters that vote for access granted, access denied (or abstain).
#See: Spring Security Reference: Chapter 13 Authorization Architecture
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>
I'm using Spring for my web app. I have used several SimpleFormControllers. I've created a session in the first SimpleFormController for the login page using:
HttpSession session = request.getSession(true);
How can I protect other SimpleFormControllers using Sessions, i.e. so that other controllers won't load if the user is not loged in.
Thank you
You probably want to use Spring Security.
It's flexible and allows restrictions based on roles.
Without it, you will need to manually check in every controller whether the user logged in or not. Or you'll have to "reinvent" a security framework by adding filter to the webapp.
If you only want to protect the operation of getting the session, you need to write a filter that wraps the original request and overrides the getSession methods. There you can check for login data using the original request's getSession().
BTW, getSession() is equivalent to getSession(true)
To protect the Controller from access outside of the intended Session, you may want to compare the Scoping rules you need with this clearly written Guide.
How to get Session Object In Spring MVC
The author gives an example of creating a Controller annotated with #Scope("session")