Copy & Paste, Struggling

This commit is contained in:
hou27
2022-06-09 22:40:43 +09:00
parent b54514acab
commit 26b0dad1ab
6 changed files with 163 additions and 3 deletions

View File

@@ -49,13 +49,17 @@ dependencies {
/* /*
Security Security
*/ */
// implementation 'org.springframework.boot:spring-boot-starter-security:2.6.7'
implementation 'org.springframework.boot:spring-boot-starter-security:2.7.0' implementation 'org.springframework.boot:spring-boot-starter-security:2.7.0'
/* /*
Validation Validation
*/ */
implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-validation'
/*
Jwt (JSON Web Token Support For The JVM)
*/
implementation 'io.jsonwebtoken:jjwt:0.9.1'
} }
tasks.named('test') { tasks.named('test') {

View File

@@ -40,7 +40,7 @@ public class SecurityConfig {
.authorizeRequests() .authorizeRequests()
.antMatchers("/", "/user/signUp", "/user/userList", "/user/signIn*").permitAll() .antMatchers("/", "/user/signUp", "/user/userList", "/user/signIn*").permitAll()
.anyRequest().authenticated(); .anyRequest().authenticated();
return http.build(); return http.build();
} }
} }

View File

@@ -0,0 +1,42 @@
package demo.api.jwt;
import demo.api.jwt.exception.CustomException;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
// Request 이전에 1회 작동할 필터
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(request);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (CustomException ex) {
//this is very important, since it guarantees the user is not authenticated at all
SecurityContextHolder.clearContext();
response.sendError(ex.getHttpStatus().value(), ex.getMessage());
return;
}
filterChain.doFilter(request, response);
}
}

View File

@@ -0,0 +1,84 @@
package demo.api.jwt;
import demo.api.jwt.exception.CustomException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import java.util.Base64;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
// 유저 정보로 JWT 토큰을 만들거나 토큰을 바탕으로 유저 정보를 가져옴
@Component
public class JwtTokenProvider {
/**
* THIS IS NOT A SECURE PRACTICE! For simplicity, we are storing a static key here. Ideally, in a
* microservices environment, this key would be kept on a config-server.
*/
@Value("${jwt.token.open-secret-key}")
private String secret_key;
@Value("${jwt.token.expire-length}")
private long expire_time;
@Autowired
private UserDetailsService userDetailsService;
@PostConstruct // 의존성 주입이 이루어진 후 초기화를 수행
protected void init() {
secret_key = Base64.getEncoder().encodeToString(secret_key.getBytes());
}
public String createToken(String username, List<AppUserRole> appUserRoles) {
Claims claims = Jwts.claims().setSubject(username);
claims.put("auth", appUserRoles.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList()));
Date now = new Date();
Date validity = new Date(now.getTime() + expire_time);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(validity)
.signWith(SignatureAlgorithm.HS256, secret_key)
.compact();
}
public Authentication getAuthentication(String token) {
UserDetails userDetails = userDetailsService.loadUserByUsername(getUsername(token));
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
public String getUsername(String token) {
return Jwts.parser().setSigningKey(secret_key).parseClaimsJws(token).getBody().getSubject();
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(secret_key).parseClaimsJws(token);
return true;
} catch (JwtException e) {
// MalformedJwtException | ExpiredJwtException | IllegalArgumentException
throw new CustomException("Error on Token", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@@ -0,0 +1,26 @@
package demo.api.jwt.exception;
import org.springframework.http.HttpStatus;
public class CustomException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final String message;
private final HttpStatus httpStatus;
public CustomException(String message, HttpStatus httpStatus) {
this.message = message;
this.httpStatus = httpStatus;
}
@Override
public String getMessage() {
return message;
}
public HttpStatus getHttpStatus() {
return httpStatus;
}
}

View File

@@ -8,4 +8,8 @@ spring:
jpa: jpa:
show-sql: true show-sql: true
hibernate: hibernate:
ddl-auto: none ddl-auto: none
jwt:
token:
secret-key: open-secret-key
expire-length: 300000