Boot20220915Application.java (서버 돌리는 용)
package com.example.boot_20220915;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
// 서비스(service), 컨트롤러(controller), 환경설정(config)
@ComponentScan(basePackages = {
"com.example.service",
"com.example.controller",
"com.example.restcontroller",
"com.example.config",
"com.example.handler",
// Field jwtUtil in com.example.restcontroller.MemberRestController required a bean of type 'com.example.jwt.JwtUtil' that could not be found.
// 이게 문제 였음. 이거 안넣으면 위에 처럼 오류남.
"com.example.jwt"
})
// @WebFilter
@ServletComponentScan(basePackages = "com.example.jwt")
// mybatis => mapper
@MapperScan(basePackages = "com.example.mapper")
@EnableRedisHttpSession
@SpringBootApplication
public class Boot20220915Application {
public static void main(String[] args) {
SpringApplication.run(Boot20220915Application.class, args);
}
}
/jwt/JwtUtil.java
package com.example.jwt;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Component
public class JwtUtil {
// 토큰 생성용 보안키
private final String SECRETKEY = "fekjkfe43jfe";
// 정보 추출용 메소드
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver){
final Claims claims = Jwts.parser().setSigningKey(SECRETKEY).parseClaimsJws(token).getBody();
return claimsResolver.apply(claims);
}
// 토큰 생성(아이디 정보를 이용한 토큰 생성)
public String generateToken(String username) {
System.out.println(username);
// ex) 30분 => 1000 * 60 * 30
long tokenValidTime = 1000 * 60 * 60 * 4; // 4시간
Map<String, Object> claims = new HashMap<>();
String token = Jwts.builder().setClaims(claims).setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + tokenValidTime))
.signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();
return token;
}
// 토큰 검증
public Boolean validateToken(String token, String userid){
// 토큰에서 아이디 정보 추출
final String username = this.extractUsername(token);
if (username.equals(userid) && !isTokenExpired(token)) {
return true;
}
return false;
}
// 토큰에서 아이디 정보 추출하기
public String extractUsername(String token){
return extractClaim(token, Claims::getSubject);
}
// 토큰에서 만료 시간 추출하기
public Date extractExpiration(String token){
return extractClaim(token, Claims::getExpiration);
}
// 토큰의 만료시간이 유효한지 확인
public Boolean isTokenExpired(String token){
// 만료시간 가져와서 현재시간보다 이전인지 확인
return this.extractExpiration(token).before(new Date());
}
}
JwtFilter.java
package com.example.jwt;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.filter.OncePerRequestFilter;
//필터를 적용하는자 하는 url설정
@WebFilter(urlPatterns = {
"/api/member/update.json",
"/api/member/updatepw.json",
"/api/member/delete.json"
})
public class JwtFilter extends OncePerRequestFilter {
@Autowired JwtUtil jwtUtil;
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
System.out.println("=======filter============"); //filter 들어 왔는지 확인
System.out.println(request.getRequestURI());
System.out.println("=======filter============");
String token = request.getHeader("TOKEN");
System.out.println("=============TOKEN============="); // token 들어 왔는지 확인
System.out.println(token.toString());
System.out.println("=============TOKEN=============");
if(token == null || token.length() == 0) {
throw new Exception(); // 강제로 오류발생 시킴
}
String userid = jwtUtil.extractUsername(token);
if(jwtUtil.validateToken(token, userid) == false){
throw new Exception();
}
// 아래 라인이 실행되어야 restcontroller로 넘어감
filterChain.doFilter(request, response);
}
catch(Exception e) {
e.printStackTrace();
response.sendError(-1, "token error");
}
}
}
MemberRestController.java
package com.example.restcontroller;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.dto.MemberDTO;
import com.example.jwt.JwtUtil;
import com.example.mapper.MemberMapper;
@RestController
@RequestMapping(value = "/api/member")
public class MemberRestController {
@Autowired MemberMapper mMapper;
@Autowired JwtUtil jwtUtil; //컴포넌트 객체 생성
@Autowired PasswordEncoder bcpe;
//Security에서 @Bean으로 객체를 생성했기 때문에 사용가능
@Autowired AuthenticationManager authenticationManager;
// 회원 정보 수정 => 127.0.0.1:8080/BOOT1/api/member/update.json
@PutMapping(value = "/update.json")
public Map<String, Object> updatePUT(){
Map<String, Object> retMap = new HashMap<>();
try {
retMap.put("status", 200);
} catch (Exception e) {
e.printStackTrace();
retMap.put("status", -1);
}
return retMap;
}
// 127.0.0.1:8080/BOOT1/api/member/login.json
// application/json
@PostMapping(value="/login.json")
public Map<String, Object> loginPOST(
@RequestBody MemberDTO member){
System.out.println(member.toString());
Map<String, Object> retMap = new HashMap<>();
try {
// string 권한으로 collection으로 변경
String[] strRole = { member.getRole() };
Collection<GrantedAuthority> role
= AuthorityUtils.createAuthorityList(strRole);
//CustomDetailsService와 같은 역할
UsernamePasswordAuthenticationToken
upat = new UsernamePasswordAuthenticationToken(
member.getUserid(), member.getUserpw(), role);
authenticationManager.authenticate(upat);
retMap.put("status", 200);
retMap.put("token", jwtUtil.generateToken(member.getUserid()));
}
catch(Exception e) {
e.printStackTrace();
retMap.put("status", -1);
}
return retMap;
}
// 127.0.0.1:8080/BOOT1/api/member/join.json
@PostMapping(value="/join.json")
public Map<String, Object> joinPOST(
@RequestBody MemberDTO member) {
Map<String, Object> retMap = new HashMap<>();
System.out.println(member.toString());
try {
// 암호변경후 저장
member.setUserpw( bcpe.encode(member.getUserpw() ) );
int ret = mMapper.joinMember(member);
retMap.put("status", 200);
retMap.put("result", ret);
}
catch(Exception e) {
e.printStackTrace();
retMap.put("status", -1);
}
return retMap;
}
}