728x90
반응형
ID / PW 를 사용하는데 pw를 토큰으로 써보자.
* 이방식은 refresh token으로 만료 기한을 연장하는 방식이 아니며,
access token의 만료기한만 검사.
목적 : interceptor 에서 사용자의 요청에 앞서 json token의 만료 기한을 검증한다.
pom.xml에 의존성 추가.
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
토큰 생성.
public static String createToken(UserDto user, String SECRET_KEY) {
//Header 설정
Map<String, Object> headers = new HashMap<>();
headers.put("typ", "JWT");
headers.put("alg", "HS256");
// algorithm
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// secret key
Key key = new SecretKeySpec(SECRET_KEY.getBytes(), signatureAlgorithm.getJcaName());
// 12 시간으로 유효시간 지정.
long expiredTime = 1000 * 60L * 60L * 12L;
return Jwts.builder()
.setHeader(headers)
.claim("user_id", user.getUser_id())
.claim("user_nm", user.getUser_nm())
.setExpiration(new Date(System.currentTimeMillis() + expiredTime))
.signWith(signatureAlgorithm, key)
.compact();
}
토큰 검증 :
만료 시간 만을 검증한다면,
//토큰 검증
public static boolean validateToken(String jwt, String SECRET_KEY) {
boolean result = false;
try {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY.getBytes())
.parseClaimsJws(jwt)
.getBody();
result = !claims.getExpiration().before(new Date());
} catch (ExpiredJwtException e) {
throw e;
} catch (Exception e) {
return result;
}
return result;
}
interceptor 설정.
servlet-context.xml
<interceptors>
<interceptor>
<mapping path="/**"/>
<!-- 아래 특정 url 매핑 모두 인터셉터 대상에서 제외. -->
<exclude-mapping path="/v2/api-docs"/>
<exclude-mapping path="/swagger-resources/**"/>
<exclude-mapping path="/swagger-ui.html"/>
<exclude-mapping path="/webjars/**"/>
<exclude-mapping path="/login/**"/>
<exclude-mapping path="/task/**"/>
<beans:bean id="Interceptor" class="com.tester.tet.login.JwtInterceptor"/>
</interceptor>
</interceptors>
interceptor class :
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.net.HttpHeaders;
import io.jsonwebtoken.ExpiredJwtException;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String jwt = request.getHeader(HttpHeaders.AUTHORIZATION);
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "";
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
if(!StringUtils.isEmpty(jwt)) {
try {
if(!JwtUtil.validateToken(jwt, SECRET_KEY)) {
PrintWriter out = response.getWriter();
response.setStatus(400);
jsonString = objectMapper.writeValueAsString(new LoginResponseDto(HttpStatus.BAD_REQUEST.value(), "유효하지 않은 토큰", jwt));
out.print(jsonString);
out.flush();
return false;
}
} catch (ExpiredJwtException e) {
PrintWriter out = response.getWriter();
response.setStatus(400);
jsonString = objectMapper.writeValueAsString(new LoginResponseDto(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value(), "토큰 만료 기간 경과", jwt));
out.print(jsonString);
out.flush();
return false;
}
} else {
PrintWriter out = response.getWriter();
response.setStatus(400);
jsonString = objectMapper.writeValueAsString(new LoginResponseDto(HttpStatus.BAD_REQUEST.value(), "토큰 없음", null));
out.print(jsonString);
out.flush();
return false;
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
String jwt = request.getHeader(HttpHeaders.AUTHORIZATION);
HandlerMethod method = ((HandlerMethod)handler);
String user_id = JwtUtil.getSubject(jwt, SECRET_KEY)
.get("user_id")
.toString();
String access_ip = Utils.getUserIp();
String action = request.getMethod();
String service = method.getMethod().getName();
userManageDAO.postUserHistory(user_id, access_ip, action, service);
}
}
사용자의 토큰을 API 단에서 쓰려고 한다면,
@ApiOperation(value = "task request", notes = "작업 요청(등록)")
@RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<TaskResponseDto> postTask(
@RequestBody TaskRequestDto tsk_rqst_dto
,HttpServletRequest request ) {
try {
String jwt = request.getHeader(HttpHeaders.AUTHORIZATION);
String user_id = (String) JwtUtil.getSubject(jwt,SECRET_KEY).get("user_id");
// 토큰에서 가져온 user_id를 사용한다.
tsk_rqst_dto.setCreator_id(user_id);
TaskResponseDto taskResponseDto = new TaskResponseDto();
taskResponseDto = taskService.taskValidation(tsk_rqst_dto);
if ( !taskResponseDto.getCode().equals("200")) {
return new ResponseEntity<TaskResponseDto>(taskResponseDto,HttpStatus.BAD_REQUEST);
}
int task_id = taskService.postTask(tsk_rqst_dto);
taskService.postTaskLog(task_id, tsk_rqst_dto.toString());
userManageService.postUserHistory(user_id, request, "POST","postTask");
} catch (Exception e) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream pinrtStream = new PrintStream(out);
e.printStackTrace(pinrtStream);
log_error.error(out.toString());
return new ResponseEntity<TaskResponseDto>(new TaskResponseDto("500","Internal Server Error",null),HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<TaskResponseDto>(new TaskResponseDto("200","OK",null),HttpStatus.OK);
}
320x100
반응형
'JAVA' 카테고리의 다른 글
java directory copy / progress bar (0) | 2022.06.11 |
---|---|
springboot / querydsl 설정 (0) | 2022.05.31 |
java 정규 표현식 (0) | 2022.05.09 |
java Stream (0) | 2022.03.08 |
Stack (0) | 2022.02.23 |