개발일지 - 토큰

아침7시개발·2022년 5월 25일
0

개발일지

목록 보기
15/19

토큰 발행을 위해서 restfull api를 개발해보자.
아래와 같이 gradle 환경을 구성했다.

build.gradle

...
id 'org.springframework.boot' version '2.6.7'
...
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-validation'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
	annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
	// JWT(JSON Web Token)
	implementation 'io.jsonwebtoken:jjwt:0.9.1'
}
...

application.yml

server:
  port: 8083
spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    password: [비밀번호]
    url: jdbc:mariadb://localhost:3306/[db_name]?serverTimezone=Asia/Seoul&useSSL=false&characterEncoding=utf8
    username: [유저네임]
    hikari:
      minimum-idle: 5
      maximum-pool-size: 10
      idle-timeout: 10000
      connection-timeout: 10000
      validation-timeout: 10000
      max-lifetime: 580000

  thymeleaf:
    prefix: classpath:templates/
    suffix: .html
    cache: false

  mvc:
    static-path-pattern: /static/**
    resources:
      add-mappings: true
      static-locations: classpath:/static/

  jpa:
    generate-ddl: true
    database: MYSQL
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MariaDBDialect
        ddl-auto: update
         jdbc:
          lob:
            non_contextual_creation: true
        show_sql: true
    defer-datasource-initialization: true

  messages:
    basename: i18n/messages
    encoding: UTF-8
jwt:
  header: Authorization
  access-secret: [base64로 변경된 문자]
  access-token-validity-time: 3600 #1시간
  refresh-secret:  [base64로 변경된 문자]
  refresh-token-validity-time: 86400 #24시간

...

SecurityConfig.java


@RequiredArgsConstructor
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LogManager.getLogger(SecurityConfig.class);
    @Autowired
    TokenProvider jwtTokenProvider;
    @Autowired
    JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    @Autowired
    JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/assets/**","/images/**","/error","favicon.ico","/i18n/**");
        web.httpFirewall(defaultHttpFirewall());
    }
    @Bean
    public HttpFirewall defaultHttpFirewall() {
        return new DefaultHttpFirewall();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        /*커스터마이징*/
        String idForEncode = "bcrypt";
        Map encoders = new HashMap();
        encoders.put(idForEncode, new BCryptPasswordEncoder());
        encoders.put("noop", NoOpPasswordEncoder.getInstance());
        encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
        encoders.put("sha256", new StandardPasswordEncoder());
        return new DelegatingPasswordEncoder("sha256", encoders);
        //return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        //return  new MessageDigestPasswordEncoder("SHA-256"); deprecated
        //return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // token을 사용하는 방식이기 때문에 csrf를 disable합니다.
                .csrf().disable()

                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)

                // enable h2-console
                .and()
                .headers()
                .frameOptions()
                .sameOrigin()

                // 세션을 사용하지 않기 때문에 STATELESS로 설정
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()
                .authorizeRequests()
                //로그인 api는 토큰이 없는 상태로 요청이 오기 때문에 허용
                //회원가입 api는 토큰이 없는 상태로 요청이 오기 때문에 허용
                .antMatchers([허용 url]).permitAll()
                .anyRequest().authenticated()
                .and()
                .logout()
                .logoutUrl([로그아웃 url])
                .logoutSuccessUrl([로그인 url])
                .addLogoutHandler(new CustomLogoutHandler()) // 로그아웃 핸들러
                //.logoutSuccessHandler(logoutSuccessHandler())
                .and()
                // JwtAuthenticationFilter를 UsernamePasswordAuthenticationFilter 전에 넣는다
                .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider),
                        UsernamePasswordAuthenticationFilter.class)
        ;
    }
}

JwtAuthenticationFilter.java


//해당 클래스는 JwtTokenProvider가 검증을 끝낸 Jwt로부터 유저 정보를 조회해와서 UserPasswordAuthenticationFilter 로 전달합니다.
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends GenericFilterBean {

    private final TokenProvider jwtTokenProvider;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 헤더에서 JWT 를 받아옵니다.
        String token = jwtTokenProvider.resolveToken((HttpServletRequest) request);
        // 유효한 토큰인지 확인합니다.
        if (token != null && jwtTokenProvider.validateToken(token)) {
            // 토큰이 유효하면 토큰으로부터 유저 정보를 받아옵니다.
            Authentication authentication = jwtTokenProvider.getAuthentication(token);
            // SecurityContext 에 Authentication 객체를 저장합니다.
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }
}

TokenProvider.java

/*토큰의 생성, 토큰의 유효성 검증 담당 */

@Component
public class TokenProvider {

    private final Logger logger = LoggerFactory.getLogger(TokenProvider.class);
    private final String accessSecret;
    private final long accessTokenValidityTime;
    private final String refreshSecret;
    private long refreshTokenValidityTime;
    private final CustomUserDetailService customUserDetailService;
//    @PostConstruct
//    protected void init() {
//        secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
//    }

    public TokenProvider(
              @Value("${jwt.access-secret}") String accessSecret
            , @Value("${jwt.access-token-validity-time}") long accessTokenValidityTime
            , @Value("${jwt.refresh-secret}") String refreshSecret
            , @Value("${jwt.refresh-token-validity-time}") long refreshTokenValidityTime
            , CustomUserDetailService customUserDetailService
    ) {
        this.accessSecret = accessSecret;
        this.accessTokenValidityTime = accessTokenValidityTime * 1000;
        this.refreshSecret = refreshSecret;
        this.refreshTokenValidityTime = refreshTokenValidityTime * 1000;
        this.customUserDetailService = customUserDetailService;
    }



    /**
     * authentication 파라미터를 받고 권한 설정해서
     * 토큰 리턴
     * @param userPk
     * @param roles
     * @return
     */
    public TokenDto createToken(String userPk, List<String> roles) {
        Claims claims = Jwts.claims().setSubject(userPk); // JWT payload 에 저장되는 정보단위, 보통 여기서 user를 식별하는 값을 넣는다.

        //yml에서 설정한 토큰 시간 설정
        Date now = new Date();


        String accessToken = Jwts.builder()
                .setClaims(claims) // 정보 저장
                .setIssuedAt(now) // 토큰 발행 시간 정보
                .setExpiration(new Date(now.getTime() + accessTokenValidityTime)) // set Expire Time
                .signWith(SignatureAlgorithm.HS256, accessSecret)  // 사용할 암호화 알고리즘과
                // signature 에 들어갈 secret값 세팅
                .compact();
        //Refresh Token
        String refreshToken =  Jwts.builder()
                .setClaims(claims) // 정보 저장
                .setIssuedAt(now) // 토큰 발행 시간 정보
                .setExpiration(new Date(now.getTime() + refreshTokenValidityTime)) // set Expire Time
                .signWith(SignatureAlgorithm.HS256, refreshSecret)  // 사용할 암호화 알고리즘과
                // signature 에 들어갈 secret값 세팅
                .compact();
        return TokenDto.builder().accessToken(accessToken).refreshToken(refreshToken).key(userPk).build();
    }

    // JWT 토큰에서 인증 정보 조회
    public Authentication getAuthentication(String token) {
        Member userDetails = customUserDetailService.loadUserByUsername(this.getUserPk(token));
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }

    // 토큰에서 회원 정보 추출
    public String getUserPk(String token) {
        return Jwts.parser().setSigningKey(accessSecret).parseClaimsJws(token).getBody().getSubject();
    }

    // Request의 Header에서 token 값을 가져옵니다. "Authorization" : "TOKEN값'
    public String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getParameter("access-token") != null ? request.getParameter("access-token") : request.getHeader(Constant.AUTHORIZATION_HEADER);
        logger.debug(bearerToken);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }


    // 토큰의 유효성 + 만료일자 확인
    public boolean validateToken(String jwtToken) {
        logger.debug("jwtToken = " + jwtToken);
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(accessSecret).parseClaimsJws(jwtToken);
            logger.debug("================"+claims.getBody().get("sub").toString());
            return !claims.getBody().getExpiration().before(new Date());
        } catch (Exception e) {
            logger.debug("e = " + e);
            return false;
        }
    }
    public String userCheck(String jwtToken) {
        Jws<Claims> claims = Jwts.parser().setSigningKey(accessSecret).parseClaimsJws(jwtToken);
        logger.debug("================"+claims.getBody().get("sub").toString());
        return claims.getBody().get("sub").toString();
    }
    public String validateRefreshToken(RefreshToken refreshTokenObj){

        // refresh 객체에서 refreshToken 추출
        String refreshToken = refreshTokenObj.getRefreshToken();
        try {
            // 검증
            Jws<Claims> claims = Jwts.parser().setSigningKey(refreshSecret).parseClaimsJws(refreshToken);
            //refresh 토큰의 만료시간이 지나지 않았을 경우, 새로운 access 토큰을 생성합니다.
            if (!claims.getBody().getExpiration().before(new Date())) {
                return recreationAccessToken(claims.getBody().get("sub").toString(), claims.getBody().get("roles"));
            }
        }catch (Exception e) {

            //refresh 토큰이 만료되었을 경우, 로그인이 필요합니다.
            return null;

        }

        return null;
    }

    public String recreationAccessToken(String userEmail, Object roles){

        Claims claims = Jwts.claims().setSubject(userEmail); // JWT payload 에 저장되는 정보단위
        claims.put("roles", roles); // 정보는 key / value 쌍으로 저장된다.
        Date now = new Date();

        //Access Token

        return Jwts.builder()
                .setClaims(claims) // 정보 저장
                .setIssuedAt(now) // 토큰 발행 시간 정보
                .setExpiration(new Date(now.getTime() + accessTokenValidityTime)) // set Expire Time
                .signWith(SignatureAlgorithm.HS256, accessSecret)  // 사용할 암호화 알고리즘과
                // signature 에 들어갈 secret값 세팅
                .compact();
    }

    public String createToken2(String email) {
        Claims claims = Jwts.claims().setSubject(email); // JWT payload 에 저장되는 정보단위, 보통 여기서 user를 식별하는 값을 넣는다.

        //yml에서 설정한 토큰 시간 설정
        Date now = new Date();

        return Jwts.builder()
                .setClaims(claims) // 정보 저장
                .setIssuedAt(now) // 토큰 발행 시간 정보
                .setExpiration(new Date(now.getTime() + accessTokenValidityTime)) // set Expire Time
                .signWith(SignatureAlgorithm.HS256, accessSecret)  // 사용할 암호화 알고리즘과
                // signature 에 들어갈 secret값 세팅
                .compact();
    }
}

JwtAccessDeniedHandler.java

@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        //필요한 권한이 없이 접근하려 할때 403
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}

JwtAuthenticationEntryPoint.java

//유효한 자격증명을 제공하지 않고 접근하려 할때 401에러를 리턴할 클래스
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        // 유효한 자격증명을 제공하지 않고 접근하려 할때 401
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }
}

RefreshToken.java

@Builder
@Entity
@Getter
@Table(name = "T_REFRESH_TOKEN")
@NoArgsConstructor
@AllArgsConstructor
public class RefreshToken {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Long refreshTokenId;

    @Column(nullable = false)
    private String refreshToken;

    @Column(nullable = false)
    private String keyEmail;

    @Column(nullable = false)
    private String userAgent;
}

Member.java

@ToString
@Getter
@Setter
@AllArgsConstructor
@Entity
@NoArgsConstructor
public class Member extends BaseTimeEntity implements UserDetails {
...
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return null;
    }

    @Override
    public String getUsername() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

}

CustomUserDetailService.java

@Service
public class CustomUserDetailService implements UserDetailsService {
    @Autowired
    MemberRepository memberRepository;
    @Override
    public Member loadUserByUsername(String username) throws UsernameNotFoundException {
        return memberRepository.findOneWithAuthoritiesById(username)
                .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));
    }
}

JwtService.java


@Service
@RequiredArgsConstructor
public class JwtService {
    private static final Logger logger = LogManager.getLogger(JwtService.class);
    private final TokenProvider jwtTokenProvider;
    private final RefreshTokenRepository refreshTokenRepository;
    @Transactional
    public void login(TokenDto tokenDto, String userAgent){

        RefreshToken refreshToken = RefreshToken
                .builder()
                .keyEmail(tokenDto.getKey())
                .refreshToken(tokenDto.getRefreshToken())
                .userAgent(userAgent)
                .build();
        String loginUserEmail = refreshToken.getKeyEmail();
        if(refreshTokenRepository.existsByKeyEmailAndUserAgent(loginUserEmail, userAgent)){
            logger.debug("기존의 존재하는 refresh 토큰 삭제");
            refreshTokenRepository.deleteByKeyEmailAndUserAgent(loginUserEmail, userAgent);
        }
        refreshTokenRepository.save(refreshToken);

    }

    public Optional<RefreshToken> getRefreshToken(String refreshToken){

        return refreshTokenRepository.findByRefreshToken(refreshToken);
    }

    public Map<String, String> validateRefreshToken(String refreshToken){
        RefreshToken refreshToken1 = getRefreshToken(refreshToken).get();
        String createdAccessToken = jwtTokenProvider.validateRefreshToken(refreshToken1);

        return createRefreshJson(createdAccessToken);
    }

    public Map<String, String> createRefreshJson(String createdAccessToken){

        Map<String, String> map = new HashMap<>();
        if(createdAccessToken == null){

            map.put("errortype", "Forbidden");
            map.put("status", "402");
            map.put("message", "Refresh 토큰이 만료되었습니다. 로그인이 필요합니다.");


            return map;
        }
        //기존에 존재하는 accessToken 제거


        map.put("status", "200");
        map.put("message", "Refresh 토큰을 통한 Access Token 생성이 완료되었습니다.");
        map.put("accessToken", createdAccessToken);

        return map;


    }


}

LoginDto.java

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class LoginDto {

    @NotNull
    @Size(min = 3, max = 50)
    private String email;
    @NotNull
    @Size(min = 3, max = 50)
    private String pwd;
    @NotNull
    @Size(min = 3, max = 50)
    private String site;
}

ResponseDto.java

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ResponseDto<T1, T2, T3> {
    private String error;
    private List<T1> data;
    private Map<T2,T3> map;
    private String url;
    private String msg;
    private String code;
}

TokenDto.java

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TokenDto {
    private String grantType;
    private String accessToken;
    private String refreshToken;
    private String key;
}

AuthController.java


@CrossOrigin("*")
@RequestMapping("/api")
@RestController
@RequiredArgsConstructor
public class AuthController {
    @Autowired
    HttpSession httpSession;
    private static final Logger logger = LogManager.getLogger(AuthController.class);
    private final TokenProvider jwtTokenProvider;
    private final CustomUserDetailService customUserDetailService;
    private final JwtService jwtService;

    // 로그인

    /**
     * 로그인
     * 토큰 첫 발행
     * https://backtony.github.io/spring/2021-07-12-spring-basic-8/
     * https://recordsoflife.tistory.com/360
     * @param userAgent
     * @param loginDto
     * @return
     */
    @PostMapping("/login")
    public ResponseEntity<ResponseDto> login(
            HttpServletRequest request
            , @RequestHeader("User-Agent") String userAgent
            ,@Valid @RequestBody LoginDto loginDto) {
        String email = loginDto.getEmail();
        String pwd = loginDto.getPwd();
        String url = loginDto.getSite();

        logger.debug("user email = {"+ email +"}");
        Member member = customUserDetailService.loadUserByUsername(email);
        TokenDto tokenDto = null;
        Map<String,Object>map = new HashMap<>();

        if (Objects.equals( member.getPwd(), CommonUtils.sha256(pwd) )) {
            tokenDto = jwtTokenProvider.createToken(member.getId(), member.getRoles());
       
            jwtService.login(tokenDto, userAgent);
            map.put("info",tokenDto);
            map.put("user",member);
        } else {
            return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().code("0003").build());
        }
        return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().code("0000").map(map).build());
    }
    /**
     * 로그인
     * 토큰 첫 발행
     * https://backtony.github.io/spring/2021-07-12-spring-basic-8/
     * https://recordsoflife.tistory.com/360
     * @param loginDto
     * @return
     */
    @PostMapping("/login2")
    public ResponseEntity<ResponseDto> login(
            HttpServletRequest request
            ,@Valid @RequestBody LoginDto loginDto) {
        String email = loginDto.getEmail();
        String pwd = loginDto.getPwd();
        String url = loginDto.getSite();
        logger.debug("user email = {"+ email +"}");
        Member member = customUserDetailService.loadUserByUsername(email);
        TokenDto tokenDto = null;
        Map<String,Object>map = new HashMap<>();
        if (pwd != null && Objects.equals( member.getPwd(), CommonUtils.sha256(pwd) )) {
            tokenDto = jwtTokenProvider.createToken(member.getId(), member.getRoles());
      
            String userAgent = "111";
            jwtService.login(tokenDto, userAgent);
            map.put("info",tokenDto);
            map.put("user",member);
        } else {
            throw new InputMismatchException("잘못된 비밀번호 입력");
        }
        return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().url(Constant.URLMAP.get(url)).map(map).error(null).build());
    }
    /**
     * 토큰 확인
     * @param request
     * @param userAgent
     * @return
     */
    @PostMapping("/access-token")
    public ResponseEntity<ResponseDto> access_token(
            HttpServletRequest request
            , @RequestHeader("User-Agent") String userAgent) {
        String accessToken = jwtTokenProvider.resolveToken(request);
        logger.debug(accessToken);
        boolean validAccessToken = jwtTokenProvider.validateToken(accessToken);
        ResponseDto<String,String,String>dto;
        if ( validAccessToken ) {
            //TODO
            //session 추가
            dto = ResponseDto.<String, String, String>builder().code("0000").build();
        } else {
            dto = ResponseDto.<String, String, String>builder().msg("토큰 만료").code("0001").build();
        }

        logger.debug(userAgent);

        return  ResponseEntity.ok(dto);
    }
    /**
     * 로그인 확인
     * @param request
     * @param userAgent
     * @return
     */
    @PostMapping("/check-login")
    public ResponseEntity<ResponseDto> check_login(
            HttpServletRequest request
            , HttpSession httpSession
            , @RequestHeader("User-Agent") String userAgent

    ) {

        String accessToken = jwtTokenProvider.resolveToken(request);
        logger.debug(accessToken);
        boolean validAccessToken = jwtTokenProvider.validateToken(accessToken);
        ResponseDto<String,String,String>dto;
        if ( validAccessToken ) {
            String userCheck = jwtTokenProvider.userCheck(accessToken);
            logger.debug("userCheck = " + userCheck);

            dto = ResponseDto.<String, String, String>builder().msg("유효한 토큰").build();
        } else {
            dto = ResponseDto.<String, String, String>builder().msg("만료된 토큰").build();
        }

        logger.debug(userAgent);

        return  ResponseEntity.ok(dto);
    }

    /**
     * 토큰 재발행
     * @param request
     * @param params
     * @param userAgent
     * @return
     */
    @PostMapping("/refresh")
    public ResponseEntity<ResponseDto> refresh(
            HttpServletRequest request
            , @RequestBody Map<String, String> params
            , @RequestHeader("User-Agent") String userAgent) {
        String refreshToken = params.get("refreshToken");
        if (refreshToken == null) {
            return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().code("0002").msg("토큰 없음").build());
        } else {
            RefreshToken refreshToken1 = jwtService.getRefreshToken(refreshToken).orElse(null);
     
            if (refreshToken1 != null) {
                String newAccessToken = jwtTokenProvider.validateRefreshToken(refreshToken1);
                logger.debug(newAccessToken);
                Map<String,Object>map = new HashMap<>();
                if (newAccessToken != null) {
                    boolean validAccessToken = jwtTokenProvider.validateToken(newAccessToken);
                    if ( validAccessToken ) {
                        TokenDto tokenDto = TokenDto.builder().refreshToken(refreshToken).accessToken(newAccessToken).key(refreshToken1.getKeyEmail()).build();
                        map.put("info",tokenDto);
                    }
                }
                logger.debug(userAgent);
                return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().map(map).code("0000").build());
            } else {
                return  ResponseEntity.ok(ResponseDto.<String, String, Object>builder().code("0001").msg("토큰 만료").build());
            }
        }
    }

    @GetMapping("/logout")
    public ResponseEntity<?> logout () {

        return ResponseEntity.ok("");
    }
    @PostMapping("/join")
    public ResponseEntity<?> join () {

        return ResponseEntity.ok("");
    }

    @PostMapping("/check-email")
    public ResponseEntity<?> check_email (@RequestBody String email) {
        logger.debug("email = " + email);
        Member member = customUserDetailService.loadUserByUsername(email);
        return ResponseEntity.ok(member);
    }
}

common.js

class UserInfo {
 constructor(email, pwd, site) {
  this.email = email;
  this.pwd = pwd;
  this.site = site;
 }
}
$(function (){
  //로그인 버튼 이벤트
  $('#loginButton').on('click',function(){
    const iptId = $('#iptId');
    const iptPassword = $('#iptPassword');
    if ( iptId.val().length == 0 ) {
       iptId.parent('div').siblings('.txt-error-1').css('display','');
      return;
    }
    if ( iptPassword.val().length == 0 ) {
      iptPassword.parent('div').siblings('.txt-error-1').css('display','');
      return;
    }
    $('form')[0].submit();
   // login();
  });
})
//로그인
const login = async() => {
  const id = document.getElementById('iptId').value;
  const pwd = document.getElementById('iptPassword').value;
  let user = new UserInfo(id, pwd, [site name]);

  const response = await fetch('/api/login', {
     method: 'POST',
     headers: {
         'Content-Type': 'application/json; charset=utf-8'
     },
     body: JSON.stringify(user)
  }).then((res)=> {
  return res;})
  .catch((error) =>{
    console.error(`submit data Error = [${error}]`);
  });
  console.log(response.ok);
  if (response.ok) {
    const data = await response.json();
    console.log({data});
    const accessToken = data.map.info.accessToken;
    const refreshToken = data.map.info.refreshToken;
    console.log(accessToken)
    console.log(refreshToken)
    window.localStorage.setItem('access-token', accessToken);
    window.localStorage.setItem('refresh-token', refreshToken);
    //goToPage(data.url);
  } else {
    //TODO
    //잘못 입력
  }

}

const check_login = async() => {
  const token = 'Bearer '+window.localStorage.getItem("access-token");
  const response = await fetch('/api/check-login', {
     method: 'POST',
     headers: {
         'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
         , 'Authorization' : token
     }
  }).then((res)=> {
  return res;})
  .catch((error) =>{
    console.error(`submit data Error = [${error}]`);
  });
  const data = await response.json();
}
//커스터마이징 기본 메소드
const test = async() => {
  const token = 'Bearer '+window.localStorage.getItem("access-token");
  console.log(token);
  const response = await fetch('/api/access-token', {
     method: 'POST',
     headers: {
         'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
         , 'Authorization' : token
     }
  }).then((res)=> {
  return res;})
  .catch((error) =>{
    console.error(`submit data Error = [${error}]`);
  });
  console.log(response);
  const data = await response.json();
  console.log (data);
}
//리프레시 토큰 재발행
const refresh = async() => {
  const token =  window.localStorage.getItem("refresh-token");
  const user = {
     "refreshToken" : token
    };
  console.log(token);
  const response = await fetch('/api/refresh', {
     method: 'POST',
     headers: {
         'Content-Type': 'application/json; charset=utf-8'
     },
     body: JSON.stringify(user)
  }).then((res)=> {
  return res;})
  .catch((error) =>{
    console.error(`submit data Error = [${error}]`);
  });
  console.log(response);
  if (response.ok) {
    const data = await response.json();
    console.log (data);
    const accessToken = data.map.info.accessToken;
    const refreshToken = data.map.info.refreshToken;
    window.localStorage.setItem('access-token', accessToken);
    window.localStorage.setItem('refresh-token', refreshToken);
  }
}
//페이지 변경
const goToPage = (param) => {
  console.log(param);
  location.href=param;
}
function setCookie(name, value, expiredays){
	var today = new Date();

	console.log(today.getDate())

	today.setDate(today.getDate() + expiredays); // 현재시간에 expiredays를 더함

	document.cookie = name + '=' + escape(value) + '; expires=' + today.toGMTString();

}

function getCookie(name) {

	var cookie = document.cookie;

	if (document.cookie != "") {
		var cookie_array = cookie.split("; ");
		console.log(cookie_array)
		for ( var index in cookie_array) {
			var cookie_name = cookie_array[index].split("=");
			if (cookie_name[0] == name) {
				return cookie_name[1];
			}
		}
	}
	return;
}

이런식으로 구성했다.
localstorage에서 cookie 방식으로 변경했다.

profile
쉬엄쉬엄하는 개발자

0개의 댓글