Jwt 본인 글 확인 방법

이 포스팅은 아래의 강의를 참고하였으니 여기에서 공부하시는 것을 추천드립니다.

//inf.run/tcLk

[무료] 스프링부트 시큐리티 & JWT 강의 - 인프런 | 강의

스프링부트 시큐리티에 대한 개념이 잡힙니다., - 강의 소개 | 인프런...

www.inflearn.com

1. JWT 임시 토큰을 만들어서 기본 흐름 확인하기

1) MyFilter3 자바 파일 수정하기

이전 포스팅에서 생성한 MyFilter3 자바 파일에 토큰을 확인하는 로직을 추가

package com.cos.security1.config.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class MyFilter3 implements Filter { // 토큰 값을 확인하는 필터 // 토큰 생성 시점: 정상적으로 로그인 시, 토큰을 만들어주고 토큰을 알려줌 => 사용자가 요청할 때마다 header에 Authorization에 value값으로 토큰을 가지고 요청 => 그 때 토큰이 유효한 지 검증하는 로직 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; System.out.println("filter3"); // POST 요청일 때만 확인 if(req.getMethod().equals("POST")){ String headerAuth = req.getHeader("Authorization"); // Header의 name이 'Authorization' 인 value System.out.println(headerAuth); if(headerAuth != null && headerAuth.equals("cos")){ // Authorization이 'cos' 면 토큰을 가지고 있는 것으로 간주 chain.doFilter(req,res); } else{ // 아니라면 인증이 안 된것 PrintWriter outPrintWriter = res.getWriter(); outPrintWriter.println("인증X"); } } } }

2) RestControllerAPI에 아래의 함수 추가 (아무 Controller에 추가해도 상관 X)

@PostMapping("token") public String Token(){ return "<h2>token</h2>"; }

3) 테스트

a) header의 Authorization의 value에 cos가 아닌 경우

b) header의 Authorization의 value에 cos인 경우

참고) POST 요청 테스트 방법 : postman 이용(//ajdahrdl.tistory.com/255)

개발한 API 테스트 도구 - postman

안녕하세요. 이번 포스팅에서는 개발한 API를 테스트하고 결과를 확인하는 도구인 postman에 대해서 포스팅 하겠습니다. 1. postman 가입 아래의 링크로 이동해서 편한 방법으로 가입 //www.postman.c

ajdahrdl.tistory.com

2. 로그인 시, JWT 토큰을 생성해서 반환해주기

1) PrincipalDetails 생성

package com.cos.jwt.security1.config.jwtAuth; import com.cos.jwt.security1.model.User; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.ArrayList; import java.util.Collection; @Data public class PrincipalDetails implements UserDetails { private User user; public PrincipalDetails(User user){ this.user = user; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> authorities = new ArrayList<>(); user.getRoleList().forEach(r->{ authorities.add(()->r); }); return authorities; } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }

2) PrincipalDetailsJwtService 생성

package com.cos.jwt.security1.config.jwtAuth; import com.cos.jwt.security1.Repository.UserRepository; import com.cos.jwt.security1.model.User; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class PrincipalDetailsJwtService implements UserDetailsService { private final UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("jwtAuth.PrincipalDetailsService.loadUserByUsername"); // **** 로그인 과정 **** // // 1. username과 password를 받고 // 2. 정상인지 확인. authentcationManager로 로그인 시도를 하면 PrincipalDetailsJwtService의 loadUserByUsername이 실행됨 // 3. PrincipalDetails를 세션에 담고(권한 관리를 위해서. 권한같은 정보가 없다면 세션이 필요없음) // 4. JWT 토큰을 만들고 응답 User userEntity = userRepository.findByUsername(username); System.out.println("찾은 UserEntity : " + userEntity.toString()); PrincipalDetails p = new PrincipalDetails(userEntity); return p; } }

3) JwtAuthenticationFilter 생성

package com.cos.jwt.security1.config.jwtConfig; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.cos.jwt.security1.config.jwtAuth.PrincipalDetails; import com.cos.jwt.security1.model.User; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; // spring security에서 UsernamePasswordAuthenticationFilter 가 있는데 // login 요청 시, username, pw 전송 시, UsernamePasswordAuthenticationFilter가 동작함 @RequiredArgsConstructor public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; // /login 요청을 하면 로그인 시도를 위해서 실행되는 함수 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { System.out.println("JwtAuthenticationFilter.attemptAuthentication : 로그인 시도중입니다"); try{ // 1. usernamee, pw 받기 // request로 부터 온 데이터들 확인 방법 /* BufferedReader br = request.getReader(); String input = null; while(true){ input = br.readLine(); if(input == null){ break; } System.out.println(input); } */ // request로 부터 온 데이터(JSON으로 보냈다는 가정 하에) 를 JSON 형태로 변환하기 ObjectMapper objectMapper = new ObjectMapper(); User user = objectMapper.readValue(request.getInputStream(), User.class); System.out.println(user.toString()); System.out.println("========================================1"); // 토큰 생성 (폼 로그인 시에는 자동으로 해줌) UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()); System.out.println("========================================2"); // PrincipalDetailsJwtService의 loadUserByUsername() 함수가 실행됨 Authentication authentication = authenticationManager.authenticate(authenticationToken); System.out.println("========================================3"); // 로그인을 성공했다는 뜻 PrincipalDetails principal = (PrincipalDetails) authentication.getPrincipal(); System.out.println("로그인 한 사용자 : " + principal.getUser().getUsername()); System.out.println("========================================4"); // authentication 객체가 session 영역에 저장 // 리턴하는 이유는 권한 관리를 security가 대신 해주기 때문에 편하기 위해서. // JWT 토큰을 사용한다면 세션을 사용할 필요가 없지만 권한 관리 때문에 세션을 사용하는 것 return authentication; } catch(IOException e){ e.printStackTrace(); } return null; } // attemptAuthentication 실행 후 인증이 정상적으로 완료되면 successfulAuthentication 함수가 실행됨 // JWT 토큰을 만들어서 request 요청한 사용자에게 JWT 토큰을 주면 된다. @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { System.out.println("successfulAuthetication 실행 : 인증 완료란 뜻"); PrincipalDetails principalDetails = (PrincipalDetails) authResult.getPrincipal(); // JWT 토큰 만들기 // RSA 방식이 아닌, Hash암호방식 (최근 이 방식을 더 많이 사용한다고 함) String jwtToken = JWT.create() .withSubject("토큰 제목") // 토큰 제목 .withExpiresAt(new Date(System.currentTimeMillis()+(60000*10))) // 토큰 만료시간 ms 기준 60초 * 10 (10분) .withClaim("id", principalDetails.getUser().getId()) .withClaim("username", principalDetails.getUser().getUsername()) .sign(Algorithm.HMAC512("cos")); response.addHeader("Authentication", "Bearer " + jwtToken); } }

4) 결과 확인

Toplist

최신 우편물

태그