Spring Rest 2022/04/08 Member(token), Board

무간·2022년 4월 8일
0

파일명 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);
}
profile
당신을 한 줄로 소개해보세요

0개의 댓글

관련 채용 정보