LoginSignup
11
10

More than 5 years have passed since last update.

Spring Securityの認証結果をJSONにする

Posted at

はじめに

Spring Securityで、Form認証の結果をJSONで返却するための方法を調べてみました。

私が検証したバージョンは以下となります。

Version
Java 1.8
Spring Boot 1.5.10.RELEASE

サンプルコード

論よりコード。まずはサンプルコードをご覧ください。

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() // Form認証を設定
        .successHandler(this) // 認証成功時のハンドラ指定
        .failureHandler(this); // 認証失敗時のハンドラ指定
    http.authorizeRequests().anyRequest().authenticated(); // 認証が要求されるリクエストの設定
  }


  // ------------------------------
  // AuthenticationSuccessHandler
  // ------------------------------

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request,
                                      HttpServletResponse response,
                                      Authentication authentication) throws IOException {
    MyResult result = new MyResult("認証成功"); // JSONにするオブジェクト
    HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
    httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); // 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("認証失敗"); // JSONにするオブジェクト
    HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
    httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); // Responseに書き込む
    response.setStatus(HttpStatus.UNAUTHORIZED.value()); // 401 Unauthorized.
  }


  // ------------------------------

  /** 認証結果 */
  @lombok.Value
  public static class MyResult {
    private final String message;
  }

}

ResponseをJSONにするには

successHandler1およびfailureHandler2で、Response内容にJSONを書き込めばよいようです。
また、認証失敗の場合はステータスが「401 Unauthorized.」になるようにしています。

Tips

ResponseをJSONにするための処理があっさり終わってしまったので、いろいろ試してみて気付いたTipsをご紹介します。

MappingJackson2HttpMessageConverter

Response内容にJSONを書き込む際は、MappingJackson2HttpMessageConverterを使うと便利です。
自動的にヘッダにContent-Type: application/json;charset=UTF-8もつけてくれます。

MappingJackson2HttpMessageConverterをAutowired
@Autowired
MappingJackson2HttpMessageConverter httpMessageConverter;
JSONの書き込み
httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage);

ちなみに、自力でResponseに書き込む場合は以下のようになります。3

@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);
}

ハンドラのInterface実装

上記サンプルコードのように、各種ハンドラのInterfaceをWebSecurityConfigurerの実装クラスでimplementsするとコードがすっきりします。

すっきりしている箇所の抜粋
@Configuration
public class JsonAuthConfigurer extends WebSecurityConfigurerAdapter
    implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
    // ↑このクラスでハンドラをimplementsしているので...

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        .successHandler(this) // ←ハンドラ指定の引数は、thisでよい
        .failureHandler(this); // ←ハンドラ指定の引数は、thisでよい
  }

  //...
}

おわりに

認証シリーズ第3弾です。過去の記事は以下になります。

Springにも大分慣れてきたような気がします。


  1. org.springframework.security.web.authentication.AuthenticationFailureHandler 

  2. org.springframework.security.web.authentication.AuthenticationSuccessHandler 

  3. Spring boot - return user object after log in - Stack Overflowから引用 

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10