I am learning Spring and trying to implement Springs Security. I am not able to understand how it works. I read tutorials from which I understood the following:
we have to configure web.xml for delegating proxy and pattern
we need to add intercepts to dispatcher-servlet.xml
When request is made it triggers intercepts but after that I am unable to understand how it works. It would be helpful if somebody could provide a list of steps to be followed. I am using Hibernate and Spring (both with annotations), I want to authenticate users using Hibernate.
A detailed article can be found here: Code Project Or a tutorial with MVC and Spring Security here.
I tried to illustrate the process a little bit:
The user sends a HTTP-Request to the server
The server processes the request according to the web.xml
The web.xml contains a filter (AKA interceptor) and passes the request through this filter.
Because the user is unknown/not authenticated, Spring Security does its best to get more details.Depending on the config, it
sends an HTTP header, so that a login popup pops up in the browser (client side).
redirects to a form where you can enter username and password.
does a lot of hidden interaction between server and browser to guarantee a "Single-Sign-On" (SSO)
Except for SSO the user enters her/his/its credentials and create an additional request.
Spring Security realizes the login attempt and authenticates the user against a
file with user and passwords
a built-in XML structure in a spring config file
a database
an LDAP
When the access is granted, it assignes the necessary roles...
...and redirects to hard-coded "home page". (Spring Security let's you adjust this behaviour.)
In your application you can check the authorization for certain actions
.....
The user clicks on "logout" or the session expires. With the next request the process starts again.
Annotations
I found a tutorial here (Link).
I understood/assume the following facts:
The filters still must be defined in the web.xml.
You can annotate your classes/methods with
#Controller (API)
#Secured (API)
#RequestMapping (API)
I admit that I only gave you a rough overview, because your question is not that specific.
Please let me know what you want to learn in detail (re-recognize users, authenticate against different resources, do a SSO, create a secured area on your webpage,...)
Spring uses a dispatcher servlet for delegating the request. Spring security filters the request and checks if a valid security context is established. If so the request is passed to the dispatcher and it passes the request forward to the corresponding controller. If no security context is established, Spring security intercepts the request which means he could manipulate the request before the diespatcher servlet could process it. During this interception the request dispatcher (Servlet Specification) will be assigned to forward the request to a login page.
I think you don't have to bother with xml anymore. Now you can use Spring Boot + annotation based configuration. One of the best tutorial I found is this one: A good spring security tutorial
There are some good step-by-step tutorials on how to integrate spring security. For example:
For Java config: http://jtuts.com/2016/03/03/spring-security-login-form-integration-example-with-java-configuration/
For XML config: http://jtuts.com/2016/03/02/spring-security-login-form-integration-example-with-xml-configuration/
Related
I have a Spring Boot GraphQL application that is using Spring Security to authenticate via an OAuth2 provider.
Since graphql requires POST requests with query/mutations as request body; my initial unauthenticated request is a POST. This does not work with the default WebSessionServerRequestCache because it only caches the initial request if it is a GET request.
Is there a way to configure the application so that upon successful login, the user is redirected to the original POST request they made (including the body)? Or does this require a custom Request Cache implementation?
I should add, I found this issue: https://github.com/spring-projects/spring-security/issues/9690 which is basically the exact functionality that I'm looking for but for a different reason (SAML login). And it was closed because they determined they could do things differently for their implementation. However, this application of spring security to a GraphQL application seems common enough that I thought I might be missing something obvious.
I have been following the example in this tutorial: https://spring.io/blog/2015/01/28/the-api-gateway-pattern-angular-js-and-spring-security-part-iv
In brief:
I have a server called UI that has some html and angular js.
I have a server called resource that has a RestController who is serving the content from a DB. All the calls must be authenticated.
The UI server has a login page which works with spring http basic login and creates a spring session that is stored in a Redis server and it is shared to the resource server. When i have some dummy users in memory authentication everything works fine.
The question is:
I want my UI server to be able to perform a login with real users, that exist in the DB. The UI server should not have any DB related code (not knowing its existence) but it should call a REST service in the resource server. The only way i was thinking (but is sounds wrong to me) is to implement a userDetailsService bean in the UI and the loadUserByUsername method should call a rest service from the resource server (e.g. /getUser). The rest service should return all the user details including credentials and roles for the given username. However, to my understanding, this service cannot be secured (for the call to be successful) which compromises the entire security.
I am open to all suggestions and recommendations. Bare in mind this is my first attempt to work with Spring.
Thank you in advance,
Nicolas
In case that someone is interested how i tackled this..
I decided to do the prudent thing and study spring security.. :)
My answer is to use a custom AuthenicationProvider in my UI server, which will call an unprotected rest login service in the resource server, which in turn validate the user against the DB.
If the response is successful (e.g. a user object could be returned with username, password, roles) then i will create a UsernamePasswordAuthenticationToken object out of it and return it.
If the response is NOT successful (e.g. return object was null or an exception was thrown) then i will either return null or throw an AuthenticationException, it depends on how Spring behaves... I haven't reached that part of studying yet..
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#tech-intro-authentication
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
Features
Comprehensive and extensible support for both Authentication and Authorization
Protection against attacks like session fixation, clickjacking, cross site request forgery, etc
Servlet API integration
Optional integration with Spring Web MVC
I am developing a web application using AngularJS and Spring (4.1.0.RELEASE) as the backend. Everything is currently working great. Now that the functionality is done, I would like to add Spring Security (3.2.5.RELEASE) to the project, to both authenticate, and then authorize all of the requests. As I am using Angular, all of my views are static, and never rendered by the server. Therefore, the typical Spring Security setup (with a login jsp), will not work. I have looked at many examples, and none fit my needs. I do not want to use any external frameworks like Jersey to help with the authentication, or any server-rendered views, e.g. jsps.
When I enable Spring Security, my GET requests still work fine, but my POST requests, such as my login requests, no longer work, and return a 404 error. The controllers are correctly mapped, and the URLs are valid, so I know it must have something to do with Spring Security intercepting the request and deeming it invalid. I am not sure why this is, but I think it may have something to do with the requests not having the proper headers and Spring's CSRF protection. I do not want to disable this protection. My question is, how can I define a custom login url with Spring Security, that will authenticate my login POST request, and then send back all headers necessary to enable future, authenticated requests?
EDIT: I have gotten the url to work. Is there any way to retrieve the CSRF token from an ajax call? My views are all static, and the server is first hit on the login request, so there are no jsps, and no way to get the csrf token from the server via the jsp tag libraries. The suggestion in the first answer assumes that we are on a jsp, which is not the case. Is there any way to allow CSRF protection, or do I need to disable it and perform my own request validation?
With Spring security enabled, you'll need to add the CSRF token to all POST, PATCH, PUT and DELETE requests. This can be sent in a request header and you should be able to use a GET request to get the token. The default header is X-CSRF-TOKEN=<tokenvalue>.
Source: http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html
(This is an older version of the docs, but includes a very relevant section on Ajax and Json requests.)
If you want to disable CSRF protection for a specific URL, you'll need to write a custom RequestMatcher that excludes your login URL.
In XML configuration it would look like:
<csrf request-matcher-ref="myCustomRequestMatcher"/>
See: http://blogs.sourceallies.com/2014/04/customizing-csrf-protection-in-spring-security/
I'm going to rewrite my previous question.
Glassfish redirects after form login to the last accessed resource, how do I go about to turn this off?
Our problem is that we get 415 in FF and IE because if I have a JSESSION cookie Glassfish will redirect to the last resource I tried to access but does not switch content type from (x-form-urlencoded).
Pseudo example (requests are the browsers' XMLHttpRequest):
GET /secure/resouce1 (json) -> Response "you're not logged in."
GET /login.xhtml
POST /j_secure (x-form-urlencoded) -> New location /secure/resource1 (x-form-urlencoded)
GET /secure/resource1 (x-form-urlencoded) <- HTTP ERROR 415 content type not JSON.
You will probably need to write a Filter to check for and catch that case. I like this tutorial (hoping the translation to English is understandable).
In my opinion it is better to use Basic or Digest authentication over SSL for RESTful services. Other options are including the credentials as part of the payload or creating a dedicated login service, which accepts credentials and returns a token. There are various reasons why form based authentication is less suitable for RESTful service: it requires a session, it does not use the existing HTTP Authorization and more.
If you need to call your RESTful service using AJAX then using a cookie for authentication can be a valid solution. They should only affect if the user can make a call, but not how the server responds.
If you would like to keep using form based authentication for your application I would suggest adding an additional JAAS authentication provider which will handle the RESTful services authentication. You can read more about it here.
Another option, which should be easier than JAAS, would be using Spring Security or Apache Shiro instead of the container based authentication.
Here is an example of configuring form based authentication with Spring Security. This post shows an example of how to secure RESTful services using Spring Security.
in your login page
reset the JSESSIONID cookie to prevent redirect last page
// login_form.jsp
Cookie jsess = new Cookie("JSESSIONID", null);
jsess.setMaxAge(0);
jsess.setPath(pageContext.getServletContext().getContextPath());
response.addCookie(jsess);
I have a small application with 3-4 servlets and a basic module that provide me authentication like:
public class Authentication {
public boolean isUserAuthenticated(){
....
}
}
Is there a way to check the authentication using my class BEFORE every other servlet calls, without have to add code in each of them? I'd like to avoid the check of the user for every servlet I have and for every servlet I will have to add.
Any suggestion is well accepted :)
Thanks, Roberto
Absolutely, use a servlet filter. It's the standard way of implementing security in Java Web applications.
The Java Servlet specification version
2.3 introduces a new component type, called a filter. A filter dynamically
intercepts requests and responses to
transform or use the information
contained in the requests or
responses. Filters typically do not
themselves create responses, but
instead provide universal functions
that can be "attached" to any type of
servlet or JSP page.
You can put your authentication logic in a Servlet Filter. If the filter finds a request not authenticated, it can redirect the user to a login page (or whatever).
Anything that gets to a servlet is implicitly authenticated by then.
Use Acegi Security (now Spring Security). Using Spring will also make your life easier in other ways. (Spring security works using a servlet filter as mentioned in above posts).
User Authentication can be done though servlet filters.
Check the detailed example User Authentication Filter Example