파일명 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.Service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
// 토큰을 발행 및 정보 추출용
@Service
public class JwtUtil {
private final String SECURITY_KEY = "adjfklioqewjimna134o1643isdjv";
// 1000 => 1초
private final long VALIDATE_TIME = 1000 * 60 * 60 * 9; // 9H
// 토큰 생성(아이디 정보)
public String generatorToken(String username) {
Map<String, Object> map = new HashMap<>();
String token = Jwts.builder()
.setClaims(map)
.setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + VALIDATE_TIME))
.signWith(SignatureAlgorithm.HS256, SECURITY_KEY)
.compact();
return token;
}
// 정보 추출용 메소드
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = Jwts.parser().setSigningKey(SECURITY_KEY).parseClaimsJws(token).getBody();
return claimsResolver.apply(claims);
}
// 토큰에서 아이디 추출
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 extractExpiration(token).before(new Date());
}
// 토큰이 유효한지 체크
public boolean isTokenValidation(String token, String uid) {
String username = extractUsername(token);
if (username.equals(uid) && isTokenExpired(token)) {
return true;
}
return false;
}
}
파일명 JwtRequestFilter.java
package com.example.filter;
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 com.example.jwt.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.filter.OncePerRequestFilter;
@WebFilter(urlPatterns = {"/api/customer/mypage"})
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired JwtUtil jwtUtil;
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
try {
// 토큰 가져오기
String token = request.getHeader("TOKEN");
if(token != null ){
if(token.length() > 0){
// 토큰을 이용해서 아이디 추출하기
String username = jwtUtil. extractUsername(token);
// 토큰 검증
System.out.println("========== filter ==========");
System.out.println("jwtRequestFilter : " + token);
System.out.println("username : " + username);
System.out.println("========== filter ==========");
// 컨트롤러로 이동
filterChain.doFilter(request, response);
}
}
// 토큰 없으면 오류발생
else{
throw new Exception("토큰없음");
}
}
catch(Exception e){
e.printStackTrace();
response.sendError(-1,"토큰오류");
}
}
}
파일명 MemberDTO.java
파일에 추가
// 임시로 보관하기 위한 암호
private String upw1;
파일명 CustomerRestController.java
package com.example.restcontroller;
import java.util.HashMap;
import java.util.Map;
import com.example.dto.MemberDTO;
import com.example.jwt.JwtUtil;
import com.example.mapper.MemberMapper;
import com.example.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
// backend만 구현함. 화면구현X, vue.js 또는 react.js 연동
@RestController
@RequestMapping("/api/customer")
public class CustomerRestController {
@Autowired MemberMapper mMapper;
@Autowired JwtUtil jwtUtil;
@Autowired UserDetailsServiceImpl userDetailsService;
// 마이페이지
// 127.0.0.1:9090/ROOT/api/customer/mypage
@RequestMapping(
value = "/mypage",
method = { RequestMethod.GET },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String,Object> customerMypageGET(
@RequestHeader(name = "TOKEN") String token
){
System.out.println("=============== MyPage ===============");
System.out.println(token);
String username = jwtUtil.extractUsername(token);
System.out.println(username);
// 토큰이 있어야 실행됨
Map<String, Object> map = new HashMap<>();
map.put("status",200);
return map;
}
// 암호변경 (토큰, 현재암호, 변경암호)
// 127.0.0.1:9090/ROOT/api/customer/updatepw
@RequestMapping(
value = "/updatepw",
method = { RequestMethod.PUT },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String,Object> customerUpdatePwPOST(
@RequestHeader(name = "TOKEN") String token,
@RequestBody MemberDTO member
){
// 토큰이 있어야 실행됨
Map<String, Object> map = new HashMap<>();
map.put("status",0);
try{
String username = jwtUtil.extractUsername(token);
UserDetails user = userDetailsService.loadUserByUsername(member.getUemail());
BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
// 암호화 되지 않는 것과 암호화 된것 비교하기
if( bcpe.matches(member.getUpw(), user.getPassword())){
int ret = mMapper.memberUpdatePw(username, bcpe.encode( member.getUpw1()));
if(ret ==1 ){
map.put("status",200);
}
}
}
catch(Exception e){
e.printStackTrace();
}
return map;
}
// 회원정보수정 (토큰, 이름, 전화번호)
// 127.0.0.1:9090/ROOT/api/customer/update
@RequestMapping(
value = "/update",
method = { RequestMethod.PUT },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> memberUpdatePUT(
@RequestHeader(name = "TOKEN") String token,
@RequestBody MemberDTO member
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
try{
String username = jwtUtil.extractUsername(token);
System.out.println("==========회원정보수정 토큰 username==========");
System.out.println(username);
int ret = mMapper.updateMemberOne(member, username);
System.out.println("==========회원정보수정 결과 ret==========");
System.out.println(ret);
if(ret == 1){
map.put("status",200);
}
}
catch(Exception e){
e.printStackTrace();
}
return map;
}
// 회원탈퇴 update => 중요정보 내용만 지우기 (토큰, 현재암호, 아이디를 제외한 내용 지우기)
// 127.0.0.1:9090/ROOT/api/customer/delete
@RequestMapping(
value = "/delete",
method = { RequestMethod.PUT },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> memberDeletePUT(
@RequestHeader(name = "TOKEN") String token,
@RequestBody MemberDTO member
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
try{
String username = jwtUtil.extractUsername(token);
System.out.println("==========회원탈퇴 토큰 username==========");
System.out.println(username);
UserDetails user = userDetailsService.loadUserByUsername(username);
System.out.println("==========회원탈퇴 디테일 user==========");
System.out.println(user.toString());
BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
// 암호화 되지 않는 것과 암호화 된것 비교하기
if( bcpe.matches(member.getUpw(), user.getPassword())){
int ret = mMapper.deleteMemberOne(username);
System.out.println("==========회원탈퇴 결과 ret==========");
System.out.println(ret);
if(ret == 1){
map.put("status",200);
}
}
}
catch(Exception e){
e.printStackTrace();
}
return map;
}
// 로그인
// 127.0.0.1:9090/ROOT/api/customer/login
// { "uemail": "ccc", ......}
@RequestMapping(
value = "/login",
method = { RequestMethod.POST },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String,Object> customerLoginPost(
@RequestBody MemberDTO member
){
System.out.println(member.toString());
Map<String, Object> map = new HashMap<>();
map.put("status",0); // 정상적이지 않을 때
try{
UserDetails user = userDetailsService.loadUserByUsername(member.getUemail());
BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
// 암호화 되지 않는 것과 암호화 된것 비교하기
if( bcpe.matches(member.getUpw(), user.getPassword())){
String token = jwtUtil.generatorToken( member.getUemail());
map.put("status",200); // 0 -> 200
map.put("token",token);
}
}
catch(Exception e){
e.printStackTrace();
}
return map;
}
// 회원가입(고객만)
// 127.0.0.1:9090/ROOT/api/customer/join
// {"uemail":"ggg", ...}
@RequestMapping(
value = "/join",
method = { RequestMethod.POST },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> customerJoinPost(
@RequestBody MemberDTO member
){
BCryptPasswordEncoder bcpe = new BCryptPasswordEncoder();
member.setUpw( bcpe.encode( member.getUpw()));
member.setUrole("CUSTOMER");
int ret = mMapper.memberJoin( member);
Map<String, Object> map = new HashMap<>();
map.put("status",0);
if(ret == 1){
map.put("status",200);
}
return map;
}
}
파일명 MemberMapper.java
package com.example.mapper;
import com.example.dto.MemberDTO;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
@Mapper
public interface MemberMapper {
// 회원가입
// INSERT INTO 테이블명(컬럼명들) VALUES(추가할 값들)
@Insert({
"INSERT INTO MEMBER( UEMAIL, UPW, UNAME, UPHONE, UROLE, UREGDATE )",
" VALUES( #{ obj.uemail }, #{ obj.upw }, #{ obj.uname }",
" , #{ obj.uphone }, #{ obj.urole }, CURRENT_DATE ) "
})
public int memberJoin( @Param(value = "obj") MemberDTO member);
// 로그인
// SELECT 컬럼명들 FROM 테이블명 WHERE 조건 AND 조건
@Select({
"SELECT UEMAIL, UNAME, UROLE FROM MEMBER WHERE UEMAIL = #{email} AND UPW = #{pw}"
})
public MemberDTO memberLogin(
@Param(value = "email") String em,
@Param(value = "pw") String userpw);
// security 로그인
// SELECT 컬럼명들 FROM 테이블명 WHERE 조건
@Select({
"SELECT UEMAIL, UPW, UROLE, UPHONE, UNAME FROM MEMBER WHERE UEMAIL = #{email}"
})
public MemberDTO memberEmail(
@Param(value = "email") String em);
@Update({
"UPDATE MEMBER SET UPW = #{upw}",
" WHERE UEMAIL = #{uemail}"
})
public int memberUpdatePw(
@Param(value = "uemail") String uemail,
@Param(value = "upw") String upw);
@Update({
"UPDATE MEMBER SET UNAME = #{obj.uname}, UPHONE = #{obj.uphone}",
" WHERE UEMAIL = #{uemail}"
})
public int updateMemberOne(
@Param(value = "obj") MemberDTO member,
@Param(value = "uemail") String username
);
@Update({
"UPDATE MEMBER SET UNAME = '', UPHONE = '', UROLE = '' ",
" WHERE UEMAIL = #{username}"
})
public int deleteMemberOne(@Param(value = "username") String member);
}
파일명 BoardRestController.java
package com.example.restcontroller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.example.dto.BoardDTO;
import com.example.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/board")
public class BoardRestController {
@Autowired BoardMapper bMapper;
@Value("${board.page.count}") int PAGECNT;
// 127.0.0.1:9090/ROOT/api/board/insert/
// {"btitle":"aaa", "bcontent":"bbb"}
@RequestMapping(
value = "/insert",
method = { RequestMethod.POST },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardInsertPost(
@RequestBody BoardDTO board
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
int ret = bMapper.insertBoardOne(board);
if(ret == 1){
map.put("status",200);
}
return map;
}
// 127.0.0.1:9090/ROOT/api/board/delete/
// {"bno": 3}
@RequestMapping(
value = "/delete",
method = { RequestMethod.DELETE },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardDeletePost(
@RequestParam(name = "bno") long bno
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
int ret = bMapper.deleteBoardOne(bno);
if(ret == 1){
map.put("status",200);
}
return map;
}
// 127.0.0.1:9090/ROOT/api/board/update/
// {"bno":2 , "btitle":"ccc", "bcontent": "ccc"}
@RequestMapping(
value = "/update",
method = { RequestMethod.PUT },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardUpdatePUT(
@RequestBody BoardDTO board
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
int ret = bMapper.updateBoardOne(board);
if(ret == 1){
map.put("status",200);
}
return map;
}
// 127.0.0.1:9090/ROOT/api/board/selectone?bno=2
@RequestMapping(
value = "/selectone",
method = { RequestMethod.GET },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardSelectOneGET(
@RequestParam(name = "bno") long bno
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
BoardDTO retBoard = bMapper.selectBoardOne(bno);
if(retBoard != null){
map.put("status",200);
map.put("result",retBoard);
}
return map;
}
// 게시판 목록(페이지네이션)
// 127.0.0.1:9090/ROOT/api/board/selectlist?page=1
@RequestMapping(
value = "/selectlist",
method = { RequestMethod.GET },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardSelectListGET(
@RequestParam(name = "page") int page
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
List<BoardDTO> list = bMapper.selectBoardList(
(page * PAGECNT) - (PAGECNT - 1), page+ PAGECNT);
if(list != null){
map.put("status",200);
map.put("result",list);
}
return map;
}
// 게시물의 조회수 1증가 시킴
// 127.0.0.1:9090/ROOT/api/board/updatehit?bno=2
@RequestMapping(
value = "/updatehit",
method = { RequestMethod.PUT },
consumes = { MediaType.ALL_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE})
public Map<String, Object> boardUpdateHitPUT(
@RequestParam(name = "bno") long bno
){
Map<String, Object> map = new HashMap<>();
map.put("status",0);
int ret = bMapper.updateBoardHitOne(bno);
if(ret == 1){
map.put("status",200);
}
return map;
}
}
파일명 BoardMapper.java
package com.example.mapper;
import java.util.List;
import com.example.dto.BoardDTO;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
@Mapper
public interface BoardMapper {
@Insert({
"INSERT INTO BOARD(BNO, BTITLE, BCONTENT, BHIT, BREGDATE, BTYPE, UEMAIL )",
" VALUES( SEQ_BOARD_NO.NEXTVAL, #{brd.btitle}, #{brd.bcontent, jdbcType=CLOB},",
" #{brd.bhit}, CURRENT_DATE, #{brd.btype}, #{brd.uemail})"
})
public int insertBoardOne(@Param(value = "brd") BoardDTO board);
@Delete({
"DELETE FROM BOARD WHERE BNO = #{bno}"
})
public int deleteBoardOne(@Param(value = "bno") long bno);
@Update({
"UPDATE BOARD SET BTITLE = #{brd.btitle}, BCONTENT = #{brd.bcontent, jdbcType=CLOB} ",
" WHERE BNO = #{brd.bno}"
})
public int updateBoardOne(@Param(value = "brd") BoardDTO board);
@Select({
"SELECT * FROM BOARD WHERE BNO = #{bno}"
})
public BoardDTO selectBoardOne(@Param(value = "bno") long bno);
// 페이지네이션
@Select({
"SELECT * FROM (",
" SELECT B.*, ROW_NUMBER() OVER (ORDER BY BNO DESC) ROWN FROM BOARD B",
") WHERE ROWN BETWEEN #{start} AND #{end}"
})
public List<BoardDTO> selectBoardList(
@Param(value = "start") int s,
@Param(value = "end") int e
);
// 조회수 증가
@Update({
"UPDATE BOARD SET BHIT = BHIT+1 WHERE BNO = #{bno}"
})
public int updateBoardHitOne(@Param(value = "bno") long bno);
}