Spring Rest service Security using Basic authentication
Lets discuss Spring Rest service security with basic authentication
we can make our rest services more secure by using Spring security feature.
whenever the client makes a request to secured rest service using its end point,Spring security will intercept the request to authenticate the user.
if the user is authenticated , control flows to actual rest service else it will be redirected to EntryPoint which in turn sends a 401 response to client.
Lets implement the same step by step
Create a new Maven Web project in eclipse (Refer Spring MVC Hello World project for the same)
Project structure
Step 1
Update pom.xml with below dependencies
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>SpringRestServiceSecurityBasic</groupId>
- <artifactId>SpringRestServiceSecurityBasic</artifactId>
- <packaging>war</packaging>
- <version>0.0.1-SNAPSHOT</version>
- <name>SpringRestServiceSecurityBasic Maven Webapp</name>
- <url>http://maven.apache.org</url>
- <properties>
- <org.springframework.version>4.2.0.RELEASE</org.springframework.version>
- <spring-security.version>3.2.7.RELEASE</spring-security.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <!-- Jackson JSON -->
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.8.5</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-core</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- </dependencies>
- <build>
- <finalName>SpringRestServiceSecurityBasic</finalName>
- </build>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SpringRestServiceSecurityBasic</groupId> <artifactId>SpringRestServiceSecurityBasic</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringRestServiceSecurityBasic Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <org.springframework.version>4.2.0.RELEASE</org.springframework.version> <spring-security.version>3.2.7.RELEASE</spring-security.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Jackson JSON --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring-security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring-security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring-security.version}</version> </dependency> </dependencies> <build> <finalName>SpringRestServiceSecurityBasic</finalName> </build> </project>
We have added dependencies for Spring mvc ,spring security , Jackson and Junit in the above pom file.
Step 2
Update web.xml file with Dispatcher servlet and spring security filter
we have defined a dispatcher servlet in web.xml and mapped it by the URL pattern “/”
So just like any other servlet in web application,any request matching with the given pattern i.e “/” will be redirected to “Dispatcher servlet”.
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
- <display-name>Archetype Created Web Application</display-name>
- <servlet>
- <servlet-name>mvc-dispatcher</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring-beans.xml,
- /WEB-INF/spring-security.xml
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>mvc-dispatcher</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- Loads Spring Security configuration file -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring-beans.xml,
- /WEB-INF/spring-security.xml
- </param-value>
- </context-param>
- <!-- Spring Security filter -->
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- </web-app>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-beans.xml, /WEB-INF/spring-security.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Loads Spring Security configuration file --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-beans.xml, /WEB-INF/spring-security.xml </param-value> </context-param> <!-- Spring Security filter --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
We have provided the spring configuration file name to create and load the spring beans while starting the server.
Also we have provided Spring security config file to load the security related configuration.
we have also added filter for spring security which will delegate the request for authentication before processing the request.
Step 3
Create a Spring beans config file
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
- <context:component-scan base-package="com.kb" />
- <mvc:annotation-driven />
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.kb" /> <mvc:annotation-driven /> </beans>
Step 4
Create the spring security config file
- <?xml version="1.0" encoding="UTF-8"?>
- <beans:beans xmlns="http://www.springframework.org/schema/security"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
- xmlns:sec="http://www.springframework.org/schema/security"
- xsi:schemaLocation="
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.2.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
- <!-- Rest authentication entry point configuration -->
- <http use-expressions="true" entry-point-ref="customAuthenticationEntryPoint">
- <intercept-url pattern="/rest/**" access="hasAnyRole('ROLE_ADMIN','ROLE_REST')"/>
- <form-login authentication-success-handler-ref="successHandler"
- authentication-failure-handler-ref="failureHandler" />
- <http-basic/>
- <logout />
- </http>
- <!-- Connect the custom authentication success handler -->
- <beans:bean id="successHandler"
- class="com.kb.rest.authentication.CustomSavedRequestAwareAuthenticationSuccessHandler" />
- <!-- Using default failure handler -->
- <beans:bean id="failureHandler"
- class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" />
- <!-- Authentication manager -->
- <authentication-manager alias="authenticationManager">
- <authentication-provider>
- <user-service>
- <user name="admin" password="admin" authorities="ROLE_ADMIN"/>
- <user name="rest" password="rest" authorities="ROLE_REST"/>
- <user name="user" password="user" authorities="ROLE_USER"/>
- </user-service>
- </authentication-provider>
- </authentication-manager>
- </beans:beans>
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- Rest authentication entry point configuration --> <http use-expressions="true" entry-point-ref="customAuthenticationEntryPoint"> <intercept-url pattern="/rest/**" access="hasAnyRole('ROLE_ADMIN','ROLE_REST')"/> <form-login authentication-success-handler-ref="successHandler" authentication-failure-handler-ref="failureHandler" /> <http-basic/> <logout /> </http> <!-- Connect the custom authentication success handler --> <beans:bean id="successHandler" class="com.kb.rest.authentication.CustomSavedRequestAwareAuthenticationSuccessHandler" /> <!-- Using default failure handler --> <beans:bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" /> <!-- Authentication manager --> <authentication-manager alias="authenticationManager"> <authentication-provider> <user-service> <user name="admin" password="admin" authorities="ROLE_ADMIN"/> <user name="rest" password="rest" authorities="ROLE_REST"/> <user name="user" password="user" authorities="ROLE_USER"/> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
In the above spring security xml file we have defined the entry point as “customAuthenticationEntryPoint” with the success and failure handler.
In Spring, Entry point is used to redirect the non authenticated request to get the authentication by displaying login page.
In REST Service, using entry point for displaying login page doesn’t make any sense as Rest Services most of the times will be called by some client interfaces like RestTemplate rather than a browser request.
So it is better to send the response as 401 Unauthorized when the request comes without the authentication rather than redirecting to login page to get the authentication.
success and failure handler
By default, form login will return a successful authentication with a 301 (MOVED PERMANENTLY) status code ,this makes sense in case of web applications.
In case of RESTful web service ,the expected response for a successful authentication is 200 OK.
This can be done by injecting a custom authentication success handler in the form login filter, by replacing the default one.
we have not defined any custom handler for failure handler because the default spring provider class SimpleUrlAuthenticationFailureHandler will take care of returning 401 status code.
we have also defined authentication provider as user service with set of users along with their credentials and roles defined in it.
we are granting access to Rest services only for those users whose Role is either ROLE_ADMIN or ROLE_REST as configured above.
Step 5
Create custom authentication Entry pont
- package com.kb.rest.authentication;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.AuthenticationEntryPoint;
- import org.springframework.stereotype.Component;
- @Component
- public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint{
- public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
- throws IOException, ServletException {
- System.out.println("Executing commence method due to failed Authentication");
- response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized Access!!" );
- }
- }
package com.kb.rest.authentication; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; @Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint{ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("Executing commence method due to failed Authentication"); response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized Access!!" ); } }
we have defined CustomAuthenticationEntryPoint with implementation for commence method.
This entry point is called whenever the request is missing the authentication or having invalid authentication.
and in that case, we are sending the unauthorized response to the client.
Step 6
Create Custom Authentication Success Handler
- package com.kb.rest.authentication;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
- import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
- import org.springframework.security.web.savedrequest.RequestCache;
- import org.springframework.security.web.savedrequest.SavedRequest;
- import org.springframework.util.StringUtils;
- public class CustomSavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{
- private RequestCache requestCache = new HttpSessionRequestCache();
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
- Authentication authentication) throws IOException, ServletException {
- final SavedRequest savedRequest = requestCache.getRequest(request, response);
- if (savedRequest == null) {
- clearAuthenticationAttributes(request);
- return;
- }
- final String targetUrlParameter = getTargetUrlParameter();
- if (isAlwaysUseDefaultTargetUrl()
- || (targetUrlParameter != null && StringUtils.hasText(request
- .getParameter(targetUrlParameter)))) {
- requestCache.removeRequest(request, response);
- clearAuthenticationAttributes(request);
- return;
- }
- clearAuthenticationAttributes(request);
- }
- public void setRequestCache(final RequestCache requestCache) {
- this.requestCache = requestCache;
- }
- }
package com.kb.rest.authentication; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.util.StringUtils; public class CustomSavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{ private RequestCache requestCache = new HttpSessionRequestCache(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { final SavedRequest savedRequest = requestCache.getRequest(request, response); if (savedRequest == null) { clearAuthenticationAttributes(request); return; } final String targetUrlParameter = getTargetUrlParameter(); if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request .getParameter(targetUrlParameter)))) { requestCache.removeRequest(request, response); clearAuthenticationAttributes(request); return; } clearAuthenticationAttributes(request); } public void setRequestCache(final RequestCache requestCache) { this.requestCache = requestCache; } }
we have defined a custom authentication success handler by overriding onAuthenticationSuccess method
we have just removed the redirection logic in this success handler.
Step 7
Create rest service which we want to secure
- package com.kb.rest.controllers;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.kb.rest.model.User;
- @Controller
- @RequestMapping("/rest")
- public class RestController {
- @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
- public @ResponseBody User getUserForId(@PathVariable ("id") int id) {
- User user = new User();
- user.setId(id);
- user.setName("John");
- user.setAge(45);
- return user;
- }
- }
package com.kb.rest.controllers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.kb.rest.model.User; @Controller @RequestMapping("/rest") public class RestController { @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) public @ResponseBody User getUserForId(@PathVariable ("id") int id) { User user = new User(); user.setId(id); user.setName("John"); user.setAge(45); return user; } }
we have exposed one method for retrieving the user based on id.
Step 8
Create Rest client using spring rest template without credentials
- package com.kb.rest.client;
- import org.springframework.web.client.RestTemplate;
- import com.kb.rest.model.User;
- public class GetUserClient {
- public static void main(String[] args) {
- RestTemplate restTemplate = new RestTemplate();
- final String url = "http://localhost:8080/SpringRestServiceSecurityBasic/rest/user/1";
- User user = restTemplate.getForObject(url, User.class);
- System.out.println("User retrieved details : ");
- System.out.println(user.getName() + " " + user.getAge() + " " + user.getId());
- }
- }
package com.kb.rest.client; import org.springframework.web.client.RestTemplate; import com.kb.rest.model.User; public class GetUserClient { public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); final String url = "http://localhost:8080/SpringRestServiceSecurityBasic/rest/user/1"; User user = restTemplate.getForObject(url, User.class); System.out.println("User retrieved details : "); System.out.println(user.getName() + " " + user.getAge() + " " + user.getId()); } }
Step 9
Create Rest client using spring rest template with valid credentials
- package com.kb.rest.client;
- import java.util.Arrays;
- import org.springframework.http.HttpEntity;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.MediaType;
- import org.springframework.http.ResponseEntity;
- import org.springframework.security.crypto.codec.Base64;
- import org.springframework.web.client.RestTemplate;
- import com.kb.rest.model.User;
- public class GetUserClientWithCredentials {
- /*
- * Add HTTP Authorization header, using Basic-Authentication to send user-credentials.
- */
- private static HttpHeaders getHeaders(){
- String plainCredentials="admin:admin";
- String base64Credentials = new String(Base64.encode(plainCredentials.getBytes()));
- HttpHeaders headers = new HttpHeaders();
- headers.add("Authorization", "Basic " + base64Credentials);
- headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
- return headers;
- }
- public static void main(String[] args) {
- RestTemplate restTemplate = new RestTemplate();
- final String url = "http://localhost:8080/SpringRestServiceSecurityBasic/rest/user/1";
- HttpEntity<String> request = new HttpEntity<String>(getHeaders());
- ResponseEntity<User> userResponse = restTemplate.exchange(url,HttpMethod.GET,request, User.class);
- System.out.println("User retrieved details : ");
- User user =userResponse.getBody();
- System.out.println(user.getName() + " " + user.getAge() + " " + user.getId());
- }
- }
package com.kb.rest.client; import java.util.Arrays; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.codec.Base64; import org.springframework.web.client.RestTemplate; import com.kb.rest.model.User; public class GetUserClientWithCredentials { /* * Add HTTP Authorization header, using Basic-Authentication to send user-credentials. */ private static HttpHeaders getHeaders(){ String plainCredentials="admin:admin"; String base64Credentials = new String(Base64.encode(plainCredentials.getBytes())); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Basic " + base64Credentials); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); return headers; } public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); final String url = "http://localhost:8080/SpringRestServiceSecurityBasic/rest/user/1"; HttpEntity<String> request = new HttpEntity<String>(getHeaders()); ResponseEntity<User> userResponse = restTemplate.exchange(url,HttpMethod.GET,request, User.class); System.out.println("User retrieved details : "); User user =userResponse.getBody(); System.out.println(user.getName() + " " + user.getAge() + " " + user.getId()); } }
Step 10
Build and deploy the project
Step 11
Let’s access the rest service using different clients
access below url in Browser
http://localhost:8080/SpringRestServiceSecurityBasic/rest/user/1
Run GetUserClient.java which does not have credentials
output
Run GetUserClientWithCredentials.java which has valid credentials
output
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
“Unauthorized: Authentication token was either missing or invalid.”);
the above line of code is not working , the exception is not getting caught and redirection not happening .can u plese suggest the solution
Try to clear cache and try.
Also debug , is it going to failure handler ?
Hello, Thanks for great tutorial. Every thing work well form me, but I got a problem. I used admin/admin for basic authentication in postman of chrome. After running, first time I get the 200 ok but when I change the password with wrong one and send the request again it give me again 200 ok. But it should send the 401 since I have wrong password.
Hi, Thanks!!
I think, it may be a cache issue,Please clear the cache and try again or check in incognito mode.
Thanks, I think it was cashe problem. I have changed the CustomAuthenticationEntryPoint class to return the JSON object when a user not inter his username and passwrd: I do something link this:
response.setContentType(“application/json”);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getOutputStream().println(“{ \”401\”: \”” + “Please write your username and password ” + “\” }”);
It work well and I get the JSON Object.
But the problem is how could I override SimpleUrlAuthenticationFailureHandler to return the JSON instead of default 401 unauthorized, Here is a simple class that I created but I cant figure out how to produce json object:
public class RestLoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
// ??????? Here I want the code to retun the rest
}
}