In Spring Security, I tried to find out how to return the result of Form authentication in JSON.
The version I verified is as follows.
Version | |
---|---|
Java | 1.8 |
Spring Boot | 1.5.10.RELEASE |
Code from theory. Please see the sample code first.
JsonAuthConfigurer.java
package example;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@Configuration
public class JsonAuthConfigurer extends WebSecurityConfigurerAdapter
implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
private static final MediaType CONTENT_TYPE_JSON = MediaType.APPLICATION_JSON_UTF8;
@Autowired
MappingJackson2HttpMessageConverter httpMessageConverter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //Set Form authentication
.successHandler(this) //Handler specification when authentication is successful
.failureHandler(this); //Handler specification when authentication fails
http.authorizeRequests().anyRequest().authenticated(); //Setting of requests that require authentication
}
// ------------------------------
// AuthenticationSuccessHandler
// ------------------------------
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException {
MyResult result = new MyResult("Authentication successful"); //Object to be JSON
HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); //Write to Response
response.setStatus(HttpStatus.OK.value()); // 200 OK.
}
// ------------------------------
// AuthenticationFailureHandler
// ------------------------------
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) throws IOException {
MyResult result = new MyResult("Authentication failure"); //Object to be JSON
HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); //Write to Response
response.setStatus(HttpStatus.UNAUTHORIZED.value()); // 401 Unauthorized.
}
// ------------------------------
/**Authentication result*/
@lombok.Value
public static class MyResult {
private final String message;
}
}
It seems that you should write JSON in the Response content with successHandler [^ fqcn-s] and failureHandler [^ fqcn-f]. Also, in case of authentication failure, the status is set to "401 Unauthorized."
Tips Since the process to make Response into JSON has been completed easily, I will introduce the tips that I noticed after trying various things.
MappingJackson2HttpMessageConverter
When writing JSON to the Response content, it is convenient to use MappingJackson2HttpMessageConverter
.
It will also automatically add Content-Type: application / json; charset = UTF-8
to the header.
Autowired MappingJackson2HttpMessageConverter
@Autowired
MappingJackson2HttpMessageConverter httpMessageConverter;
Write JSON
httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage);
By the way, if you write to Response by yourself, it will be as follows. [^ quote-1]
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.getWriter().write(new ObjectMapper().writeValueAsString(new UserAuthenticationResponse(authentication.getName(), 123l)));
response.setStatus(200);
}
As shown in the sample code above, implementing the Interface of various handlers in the implementation class of WebSecurityConfigurer will make the code cleaner.
Excerpt of a clean part
@Configuration
public class JsonAuthConfigurer extends WebSecurityConfigurerAdapter
implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
//↑ Because the handler is implemented in this class...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.successHandler(this) //← The argument of the handler specification may be this
.failureHandler(this); //← The argument of the handler specification may be this
}
//...
}
This is the third certification series. Past articles are as follows.
-Use Basic Authentication with Spring Boot -How to implement authentication process by specifying user name and password in Spring Boot
I feel like I'm getting used to Spring.
Recommended Posts