번외) Json 받아서 폼로그인하기

강한친구·2022년 8월 9일
0

이걸 왜?

프론트분들이 Json으로만 보낼수 있다고 하셔가지고 formLogin 받아보려고 이거저거 찾아가면서 개발했는데 결국 안쓰게 된 비운의 코드이다.

이 글을 참고하자.

JsonIdPwAuthenticationFilter

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

0개의 댓글