diff --git a/JWT/build.gradle b/JWT/build.gradle index 8a89906..b84a5c4 100644 --- a/JWT/build.gradle +++ b/JWT/build.gradle @@ -44,7 +44,9 @@ dependencies { // Swagger implementation 'io.springfox:springfox-boot-starter:3.0.0' implementation 'io.springfox:springfox-swagger-ui:3.0.0' - implementation 'io.springfox:springfox-swagger2:2.9.2' +// implementation 'io.springfox:springfox-swagger2:2.9.2' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + // // Spring Security testImplementation 'org.springframework.security:spring-security-test' diff --git a/JWT/src/main/java/JWTLogIn/JWT/user/config/SecurityConfig.java b/JWT/src/main/java/JWTLogIn/JWT/user/config/SecurityConfig.java index 2751e34..369c9b5 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/user/config/SecurityConfig.java +++ b/JWT/src/main/java/JWTLogIn/JWT/user/config/SecurityConfig.java @@ -3,11 +3,14 @@ import JWTLogIn.JWT.user.security.JwtFilter; import JWTLogIn.JWT.user.service.UserService; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.WebSecurityCustomizer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -17,6 +20,7 @@ @Configuration @EnableWebSecurity // request를 filterchain에서 가로채도록 하는 장치 @RequiredArgsConstructor +@Log4j2 public class SecurityConfig { private final UserService userService; @@ -24,6 +28,37 @@ public class SecurityConfig { @Value("${jwt.secret}") private String secretKey; + private static final String[] PERMIT_URL_ARRAY = { + /* swagger v2 */ + "/v2/api-docs", + "/swagger-resources", + "/swagger-resources/**", + "/configuration/ui", + "/configuration/security", + "/swagger-ui.html", + "/webjars/**", + /* swagger v3 */ + "/v3/api-docs/**", + "/swagger-ui/**", + "/swagger-ui/swagger-ui-standalone-preset.js", + "/swagger-ui/swagger-initializer.js", + "/swagger-ui/swagger-ui-bundle.js", + "/swagger-ui/swagger-ui.css", + "/swagger-ui/index.css", + "/swagger-ui/favicon-32x32.png", + "/swagger-ui/favicon-16x16.png", + "/api-docs/json/swagger-config", + "/api-docs/json" + }; + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + log.info("WebSecurity......................"); + + return web -> web.ignoring() + .requestMatchers(PathRequest.toStaticResources().atCommonLocations()); + } + @Bean // 요청이 들어오면 SecurityFilterChain이 가로채서 인증, 인가를 체크함. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @@ -32,8 +67,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .csrf(AbstractHttpConfigurer::disable) // 토큰 사용하기에 csrf 불가능 .cors(AbstractHttpConfigurer::disable) .authorizeHttpRequests(request -> request - .requestMatchers("/tgwing.kr", "/tgwing.kr/register", "/tgwing.kr/login", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html", - "/webjars/**", "/swagger-resources/**") + .requestMatchers("/tgwing.kr", "/tgwing.kr/register", "/tgwing.kr/login") + .permitAll() + .requestMatchers(PERMIT_URL_ARRAY) .permitAll() .anyRequest().authenticated() ) diff --git a/JWT/src/main/java/JWTLogIn/JWT/user/config/Swagger.java b/JWT/src/main/java/JWTLogIn/JWT/user/config/Swagger.java deleted file mode 100644 index 8797333..0000000 --- a/JWT/src/main/java/JWTLogIn/JWT/user/config/Swagger.java +++ /dev/null @@ -1,30 +0,0 @@ -package JWTLogIn.JWT.user.config; - -import org.springframework.context.annotation.Bean; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; - -public class Swagger { - @Bean - public Docket api() { - return new Docket(DocumentationType.OAS_30) - .useDefaultResponseMessages(false) - .select() - .apis(RequestHandlerSelectors.basePackage("JWTLogin.JWT")) - .paths(PathSelectors.any()) - .build() - .apiInfo(apiInfo()); - } - - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - .title("Hello Swagger") - .description("스웨거 기능 테스트") - .version("1.0") - .build(); - } -} \ No newline at end of file diff --git a/JWT/src/main/java/JWTLogIn/JWT/user/security/JwtFilter.java b/JWT/src/main/java/JWTLogIn/JWT/user/security/JwtFilter.java index 9b94613..b6d22de 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/user/security/JwtFilter.java +++ b/JWT/src/main/java/JWTLogIn/JWT/user/security/JwtFilter.java @@ -16,6 +16,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; +import java.util.Arrays; import java.util.List; @RequiredArgsConstructor @@ -25,59 +26,71 @@ public class JwtFilter extends OncePerRequestFilter { private final UserService userService; private final String secretKey; + @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); - log.info("Authorization : {}", authorization); - // slf4j에서 log를 찍어서 확인함. + log.info("doFilterChain....................."); - if(authorization.isEmpty() || !authorization.startsWith("Bearer ")) { - log.error("권한이 없음."); + if(authorization != null && !authorization.isEmpty()) { + log.info("Authorization : {}", authorization); + // slf4j에서 log를 찍어서 확인함. - filterChain.doFilter(request, response); - return; - } - // authentication이 없을 경우, token이 없을 경우, 혹은 "Bearer "로 시작하지 않으면 block함. - // 이 때 header의 authorization의 부분에서 어떤 입력이라도 있으면 200이 됨. + if(authorization.isEmpty() || !authorization.startsWith("Bearer ")) { + log.error("권한이 없음."); + filterChain.doFilter(request, response); + return; + } + // authentication이 없을 경우, token이 없을 경우, 혹은 "Bearer "로 시작하지 않으면 block함. + // 이 때 header의 authorization의 부분에서 어떤 입력이라도 있으면 200이 됨. - String token = authorization.split(" ")[1]; - // 토큰 꺼내기 - // authorization의 첫번째 부분이 토큰이다. - // 띄워쓰기를 쪼개는 방식으로 가져갈 때, Bearer다음의 부분이 토큰이다. - // 토큰 유효기간 확인 - if(JwtUtil.isExpired(token, secretKey)) { - log.error("토큰이 만료됨."); - filterChain.doFilter(request, response); + String token = authorization.split(" ")[1]; + // 토큰 꺼내기 + // authorization의 첫번째 부분이 토큰이다. + // 띄워쓰기를 쪼개는 방식으로 가져갈 때, Bearer다음의 부분이 토큰이다. - return; - } + // 토큰 유효기간 확인 + if(JwtUtil.isExpired(token, secretKey)) { + log.error("토큰이 만료됨."); + filterChain.doFilter(request, response); + + return; + } - //Username Token에서 꺼내기 - //이를 통해 아래 UsernamePasswordAuthenticationToken에서 userName을 사용가능함. - String name = JwtUtil.getUserName(token, secretKey); + //Username Token에서 꺼내기 + //이를 통해 아래 UsernamePasswordAuthenticationToken에서 userName을 사용가능함. + String name = JwtUtil.getUserName(token, secretKey); // Level level = JwtUtil.getLevel(token, secretKey); - String studentId = JwtUtil.getStudentId(token, secretKey); + String studentId = JwtUtil.getStudentId(token, secretKey); - log.info("name : {}", name); - log.info("studentId : {}", studentId); + log.info("name : {}", name); + log.info("studentId : {}", studentId); // log.info("level : {}", level); - // 권한 부여 - UsernamePasswordAuthenticationToken authenticationToken = - new UsernamePasswordAuthenticationToken(name, null, - List.of(new SimpleGrantedAuthority("name"))); - // Detail을 넣어줌 - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + // 권한 부여 + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(name, null, + List.of(new SimpleGrantedAuthority("name"))); + // Detail을 넣어줌 + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); // authenticationToken.setDetails(level); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - filterChain.doFilter(request, response); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + filterChain.doFilter(request, response); + } + + else { + log.info("authorization null......"); +// if(Arrays.stream(PERMIT_URL_ARRAY).anyMatch(req -> request.getRequestURI().equals(req))) { + filterChain.doFilter(request, response); + + } }// 관문. 이곳을 통과해서 지나감. }// 권한을 부여해줌. 본래 authenticate를 통과해야하는 상태를 통과하게 해줌.