로그인 기능 작업중.
parent
40318e86ef
commit
8738a08189
|
|
@ -62,7 +62,7 @@ function EgovLoginContent(props) {
|
||||||
const submitFormHandler = (e) => {
|
const submitFormHandler = (e) => {
|
||||||
console.log("EgovLoginContent submitFormHandler()");
|
console.log("EgovLoginContent submitFormHandler()");
|
||||||
|
|
||||||
const loginUrl = "/auth/login"
|
const loginUrl = "/login"
|
||||||
const requestOptions = {
|
const requestOptions = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -101,30 +101,4 @@ public class EgovLoginApiController extends BaseController {
|
||||||
}
|
}
|
||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 로그아웃한다.
|
|
||||||
* @return resultVO
|
|
||||||
* @exception Exception
|
|
||||||
*/
|
|
||||||
@Operation(
|
|
||||||
summary = "로그아웃",
|
|
||||||
description = "로그아웃 처리(JWT,일반 관계 없이)",
|
|
||||||
tags = {"EgovLoginApiController"}
|
|
||||||
)
|
|
||||||
@ApiResponses(value = {
|
|
||||||
@ApiResponse(responseCode = "200", description = "로그아웃 성공"),
|
|
||||||
})
|
|
||||||
@GetMapping(value = "/logout")
|
|
||||||
public ResultVO actionLogoutJSON(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
|
||||||
|
|
||||||
ResultVO resultVO = new ResultVO();
|
|
||||||
|
|
||||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
|
||||||
|
|
||||||
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
|
||||||
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
|
||||||
|
|
||||||
return resultVO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.dbnt.kcscbackend.config.security;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class JsonUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||||
|
|
||||||
|
private static final String DEFAULT_LOGIN_REQUEST_URL = "/login"; // /login/oauth2/ + ????? 로 오는 요청을 처리할 것이다
|
||||||
|
private static final String HTTP_METHOD = "POST"; //HTTP 메서드의 방식은 POST 이다.
|
||||||
|
private static final String CONTENT_TYPE = "application/json";//json 타입의 데이터로만 로그인을 진행한다.
|
||||||
|
private static final AntPathRequestMatcher DEFAULT_LOGIN_PATH_REQUEST_MATCHER =
|
||||||
|
new AntPathRequestMatcher(DEFAULT_LOGIN_REQUEST_URL, HTTP_METHOD); //=> /login 의 요청에, POST로 온 요청에 매칭된다.
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public JsonUsernamePasswordAuthenticationFilter(ObjectMapper objectMapper,
|
||||||
|
AuthenticationSuccessHandler authenticationSuccessHandler, // 로그인 성공 시 처리할 핸들러
|
||||||
|
AuthenticationFailureHandler authenticationFailureHandler // 로그인 실패 시 처리할 핸들러
|
||||||
|
) {
|
||||||
|
|
||||||
|
super(DEFAULT_LOGIN_PATH_REQUEST_MATCHER); // 위에서 설정한 /oauth2/login/* 의 요청에, GET으로 온 요청을 처리하기 위해 설정한다.
|
||||||
|
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
setAuthenticationSuccessHandler(authenticationSuccessHandler);
|
||||||
|
setAuthenticationFailureHandler(authenticationFailureHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
|
||||||
|
|
||||||
|
if (request.getContentType() == null || !request.getContentType().equals(CONTENT_TYPE)) {
|
||||||
|
throw new AuthenticationServiceException("Authentication Content-Type not supported: " + request.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginDto loginDto = objectMapper.readValue(StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8), LoginDto.class);
|
||||||
|
|
||||||
|
String username = loginDto.getUsername();
|
||||||
|
String password = loginDto.getPassword();
|
||||||
|
|
||||||
|
if (username == null || password == null) {
|
||||||
|
throw new AuthenticationServiceException("DATA IS MISS");
|
||||||
|
}
|
||||||
|
|
||||||
|
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
||||||
|
// Allow subclasses to set the "details" property
|
||||||
|
setDetails(request, authRequest);
|
||||||
|
return this.getAuthenticationManager().authenticate(authRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
|
||||||
|
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class LoginDto {
|
||||||
|
String username;
|
||||||
|
String password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +1,27 @@
|
||||||
package com.dbnt.kcscbackend.config.security;
|
package com.dbnt.kcscbackend.config.security;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.auth.entity.UserInfo;
|
import com.dbnt.kcscbackend.auth.entity.UserInfo;
|
||||||
|
import com.dbnt.kcscbackend.auth.service.EgovLoginService;
|
||||||
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
|
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
|
||||||
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationEntryPoint;
|
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationEntryPoint;
|
||||||
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter;
|
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
|
||||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
|
|
@ -24,6 +34,7 @@ import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
@ -39,10 +50,14 @@ import java.util.Arrays;
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EgovJwtTokenUtil jwtTokenUtil;
|
private EgovJwtTokenUtil jwtTokenUtil;
|
||||||
|
@Resource(name = "loginService")
|
||||||
|
private UserDetailsService loginService;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
//Http Methpd : Get 인증예외 List
|
//Http Methpd : Get 인증예외 List
|
||||||
private String[] AUTH_GET_WHITELIST = {
|
private String[] AUTH_GET_WHITELIST = {
|
||||||
|
|
@ -55,6 +70,7 @@ public class SecurityConfig {
|
||||||
private String[] AUTH_WHITELIST = {
|
private String[] AUTH_WHITELIST = {
|
||||||
"/",
|
"/",
|
||||||
"/login/**",
|
"/login/**",
|
||||||
|
"/login",
|
||||||
"/auth/login-jwt",//JWT 로그인
|
"/auth/login-jwt",//JWT 로그인
|
||||||
"/auth/login",//일반 로그인
|
"/auth/login",//일반 로그인
|
||||||
"/auth/join",//회원가입
|
"/auth/join",//회원가입
|
||||||
|
|
@ -107,22 +123,26 @@ public class SecurityConfig {
|
||||||
.antMatchers(AUTH_WHITELIST).permitAll()
|
.antMatchers(AUTH_WHITELIST).permitAll()
|
||||||
.antMatchers(HttpMethod.GET,AUTH_GET_WHITELIST).permitAll()
|
.antMatchers(HttpMethod.GET,AUTH_GET_WHITELIST).permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
).sessionManagement((sessionManagement) ->
|
);
|
||||||
|
http.sessionManagement((sessionManagement) ->
|
||||||
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
)
|
);
|
||||||
.cors().and()
|
|
||||||
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
|
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
|
||||||
.exceptionHandling(exceptionHandlingConfigurer ->
|
.exceptionHandling(exceptionHandlingConfigurer ->
|
||||||
exceptionHandlingConfigurer
|
exceptionHandlingConfigurer
|
||||||
.authenticationEntryPoint(new JwtAuthenticationEntryPoint())
|
.authenticationEntryPoint(new JwtAuthenticationEntryPoint())
|
||||||
)
|
);
|
||||||
.cors().and()
|
|
||||||
.formLogin().loginProcessingUrl("/auth/login")
|
http.httpBasic().disable()
|
||||||
.successHandler(loginSuccessHandler())
|
.csrf().disable()
|
||||||
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
.formLogin().disable();
|
||||||
.logoutSuccessUrl("/")
|
|
||||||
.invalidateHttpSession(true)
|
// http.authorizeHttpRequests()
|
||||||
.deleteCookies("JSESSIONID");
|
// .requestMatchers(new AntPathRequestMatcher("/auth/login")).permitAll()
|
||||||
|
// .anyRequest().authenticated();
|
||||||
|
|
||||||
|
http.cors().and().addFilterBefore(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,5 +158,33 @@ public class SecurityConfig {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationFailureHandler loginFailureHandler(){
|
||||||
|
return (request, response, exception) -> {
|
||||||
|
new DefaultRedirectStrategy().sendRedirect(request, response, "/login-error");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() {
|
||||||
|
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter(objectMapper, loginSuccessHandler(), loginFailureHandler());
|
||||||
|
jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
|
||||||
|
return jsonUsernamePasswordAuthenticationFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager() {
|
||||||
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||||
|
|
||||||
|
provider.setPasswordEncoder(passwordEncoder());
|
||||||
|
provider.setUserDetailsService(loginService);
|
||||||
|
|
||||||
|
return new ProviderManager(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new Pbkdf2PasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,4 +5,4 @@ Globals.pageUnit=10
|
||||||
Globals.pageSize=10
|
Globals.pageSize=10
|
||||||
|
|
||||||
#JWT secret key
|
#JWT secret key
|
||||||
Globals.jwt.secret = egovframe
|
Globals.jwt.secret = qWwMroux3QtiIJcPSIZARNTZEBBnWVH0jZ2Lx7tfFChCYi0ViZllo1bekZdiU0B3FRjJI7g90n0ha120dwlz8JZU8rOkmNCe9Uq0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue