프론트분들이 Json으로만 보낼수 있다고 하셔가지고 formLogin 받아보려고 이거저거 찾아가면서 개발했는데 결국 안쓰게 된 비운의 코드이다.
이 글을 참고하자.
public class JsonIdPwAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JsonIdPwAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
ObjectMapper objectMapper = new ObjectMapper();
String body = request.getReader().lines().collect(Collectors.joining());
MemberLoginDto loginDto = objectMapper.readValue(body, MemberLoginDto.class);
String username = loginDto.getUsername();
String password = loginDto.getPassword();
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, password);
usernamePasswordAuthenticationToken.setDetails((super.authenticationDetailsSource.buildDetails(request)));
return super.getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
}
// Gson 말고 ObjectMapper로도 가능함
// private Map<String, Object> parseJsonMap(HttpServletRequest request) throws IOException {
// String body = request.getReader().lines().collect(Collectors.joining());
// System.out.println("body = " + body);
// GsonJsonParser gsonJsonParser = new GsonJsonParser();
// return gsonJsonParser.parseMap(body);
// }
}
json으로 넘어온 username, password를 UserPassowrdAuthentication으로 변환해주는 필터이다.
json을 파싱해서 loginDto로 파싱하고 그 안에서 username, password를 꺼낸다. 그리고 이 값들을 이용해서 UsernamePassowordToken을 만들고
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
AuthenticationManager의 authenticate 함수의 인자로 넣는다.
public interface AuthenticationManager {
/**
* Attempts to authenticate the passed {@link Authentication} object, returning a
* fully populated <code>Authentication</code> object (including granted authorities)
* if successful.
* <p>
* An <code>AuthenticationManager</code> must honour the following contract concerning
* exceptions:
* <ul>
* <li>A {@link DisabledException} must be thrown if an account is disabled and the
* <code>AuthenticationManager</code> can test for this state.</li>
* <li>A {@link LockedException} must be thrown if an account is locked and the
* <code>AuthenticationManager</code> can test for account locking.</li>
* <li>A {@link BadCredentialsException} must be thrown if incorrect credentials are
* presented. Whilst the above exceptions are optional, an
* <code>AuthenticationManager</code> must <B>always</B> test credentials.</li>
* </ul>
* Exceptions should be tested for and if applicable thrown in the order expressed
* above (i.e. if an account is disabled or locked, the authentication request is
* immediately rejected and the credentials testing process is not performed). This
* prevents credentials being tested against disabled or locked accounts.
* @param authentication the authentication request object
* @return a fully authenticated object including credentials
* @throws AuthenticationException if authentication fails
*/
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
이러한 과정을 통해서 인증이 되면, 기존의 로그인 방식과 동일하게 처리가 된다.
configure에는 필터를 추가해주기만 하면 된다.
@Override // 설정
protected void configure(HttpSecurity http) throws Exception {
JsonIdPwAuthenticationFilter jsonAuthenticationFilter = new JsonIdPwAuthenticationFilter(LOGIN_REQUEST_MATCHER);
jsonAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/login", "/logout", "/", "/signUp").permitAll()
.anyRequest().authenticated();
http
.logout().deleteCookies("JSESSIONID")
.logoutSuccessUrl("/");
http.sessionManagement()
.maximumSessions(1).maxSessionsPreventsLogin(true);
http.addFilterAt(jsonAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}