스프링


 

1) 스프링부트 2.7.0  사용

2) jwt 라이브러리 사용 

		<dependency>
		    <groupId>com.auth0</groupId>
		    <artifactId>java-jwt</artifactId>
		    <version>3.19.2</version>
		</dependency>

 

 

JWT 설정에 전체적인 프로젝트  디렉토리 구조는 다음과 같다.

 

 

1. creae database

create user `jwt1`@`localhost` identified by '1234';    
create database jwt1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;  
grant all privileges on jwt1.* to `jwt1`@`localhost` ;

use jwt1;

 

 

 

2.라이브러리

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		
		<dependency>
		    <groupId>com.auth0</groupId>
		    <artifactId>java-jwt</artifactId>
		    <version>3.19.2</version>
		</dependency>
			
		
	</dependencies>

 

 

 

 

 

3. User  entitiy  및  UserRepository 생성

User

package com.cos.jwt.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;
import lombok.ToString;

@Data
@Entity
@ToString
public class User {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	@Column(nullable = false, unique = true)
	private String username;
	@Column(nullable = false, unique = true)
	private String email;
	private String password;
	private String roles; //USER, ADMIN
	
	public List<String> getRoleList(){
		if(this.roles.length() >0) {
			return Arrays.asList(this.roles.split(","));			
		}		
		return new ArrayList<>();
	}
		
}

 

 

UserRepository

package com.cos.jwt.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.cos.jwt.model.User;

//CRUD 함수를 JpaRepository 가 들고 있음.
//@Repostiory 라는 어노테이션이 없어도 loC가 된다. 이유는 JpaRepository 상속했기 때문에.... 가능
public interface UserRepository extends JpaRepository<User, Long>{

	//findBy 규칙 -> Username 문법
	//select * from user where username =1?
	public User findByUsername(String username);
	

	// select * from user where email = ?
	//Jpa Query Method
	public User findByEmail(String email);
	
	
	
}

 

 

 

 

4. RestApiController  생성
 

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.cos.jwt.auth.PrincipalDetails;
import com.cos.jwt.model.User;
import com.cos.jwt.repository.UserRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequiredArgsConstructor
@Slf4j
public class RestApiController {

	
	private final UserRepository userRepository;
	
	
	private final BCryptPasswordEncoder bCryptPasswordEncoder;
	
	
	@GetMapping("/home")
	public String home() {
		log.info(" home ");
		return "<h1>home</h1>";
	}
	
	

	@PostMapping("/token")
	public String token() {	
		return "<h1>token</h1>";
	}
	
	
	
	@GetMapping("admin/users")
	public List<User> users(){
		return userRepository.findAll();
	}
	
	
	@PostMapping("join")
	public String join(@RequestBody User user) {
		log.info("회원 가입 파라미터 : {} " , user.toString());
		user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
		user.setRoles("ROLE_USER");
		userRepository.save(user);
		return "회원가입완료";
	}
	
	//user, manager, admin 권한만 가능
	@GetMapping("/api/v1/user")
	public String user(Authentication authentication){
		PrincipalDetails principalDetails=(PrincipalDetails)authentication.getPrincipal();		
		log.info("/api/v1/user - Authentication  "  +principalDetails.getUsername());
		return "user";
	}
	

	//manager, admin 권한만 가능
	@GetMapping("/api/v1/manager")
	public String manager(){
		return "manager";
	}
	
	//admin 권한만 가능
	@GetMapping("/api/v1/admin")
	public String admin(){
		return "admin";
	}
	
	
}


 

 

 

 

 

5. SecurityConfig , CosConfig 생성

SecurityConfig

package com.cos.jwt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;

import com.cos.jwt.filter.MyFilter3;
import com.cos.jwt.jwt.JwtAuthenticationFilter;
import com.cos.jwt.jwt.JwtAuthorizationFilter;
import com.cos.jwt.repository.UserRepository;

import lombok.RequiredArgsConstructor;


@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter{
	
	
	private final CorsFilter corsFilter;
	private final UserRepository userRepository;
	

	// 해당 메서드의 리턴되는 오브젝트를 IoC 로 등록해 준다.
	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//The type SecurityContextPersistenceFilter is deprecated
		//http.addFilterBefore(new MyFilter3("SecurityFilter"), SecurityContextPersistenceFilter.class);
		//시큐리티 필터에 정의된 필터가 FilterConfig 의 필터보다 가장 먼저 실행 처리 된다.
		//http.addFilterBefore(new MyFilter3(), BasicAuthenticationFilter.class);		


		http.csrf().disable();						
		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//1.세션을 사용하지 않겠다.

		.and().addFilter(corsFilter)  //2.Cross-Origin 정책 사용 X 모든 요청 허용  -  @CrossOrigin과의 차이점 : @CrossOrigin은 인증이 없을 때 문제, 그래서 직접 시큐리티 필터에 등록!
			
		.formLogin().disable() //3.폼로그인 비활성화
		.httpBasic().disable() //4. basic 비활성화 기본 http 방식 안씀. 
		
		.addFilter(new JwtAuthenticationFilter(authenticationManager())) 
		.addFilter(new JwtAuthorizationFilter(authenticationManager(), userRepository))
		.authorizeHttpRequests()
				
		.antMatchers("/api/v1/user/**").hasAnyAuthority("ROLE_USER","ROLE_MANAGER","ROLE_ADMIN")				
		.antMatchers("/api/v1/manager/**").hasAnyAuthority("ROLE_MANAGER","ROLE_ADMIN")				
		.antMatchers("/api/v1/admin/**").hasAnyAuthority("ROLE_ADMIN")		
		.anyRequest().permitAll();		
	}
	
	
	
	
}

 

CosConfig

package com.cos.jwt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import lombok.extern.slf4j.Slf4j;

@Configuration
@Slf4j
public class CosConfig { //크로스 오리진 정책 설정

	/**
		Cross-Domain 의 의미는,
		IP 주소가 다르거나 Port 번호가 다른 곳에서 리소스를 가져오는 것을 금지한다는 것이다.
	*/	
	@Bean
	public CorsFilter corsFilter(){		
		log.info("cors Filter");
		UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
		CorsConfiguration config=new CorsConfiguration();
		config.setAllowCredentials(true); //내서버가 응답을 할 때 json을 자바스크립트에서 처리할 수 있게 할지를 설정하는 것
		config.addAllowedOrigin("*");//모든 ip 에 응답을 허용하겠다.		
		config.addAllowedHeader("*"); //모든 header 에 응답을 허용하겠다.
		config.addAllowedMethod("*");// 모든 post, get,put , delete, patch 허용하겠다.
		source.registerCorsConfiguration("/api/**", config);  // /api/** 로 들어오는 모든 요청들은 config를 따르도록 등록!		
		return new CorsFilter(source);
	}
	
	
	
}

 

 

 

 

6. PrincipalDetails  ,   PricipalDetailsService

PrincipalDetails

package com.cos.jwt.auth;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.cos.jwt.model.User;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
public class PrincipalDetails implements UserDetails {

	private static final long serialVersionUID = 1L;

	private User user;

	public PrincipalDetails(User user) {
		this.user = user;
	}

	/**
	 * 사용자에게 부여된 권한을 반환합니다. null을 반환할 수 없습니다.
	 */
	//해당 User 의 권한을 리턴하는 곳!!
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		Collection<GrantedAuthority> authorities=new ArrayList<>();
		user.getRoleList().forEach(res->{
			authorities.add(()->res);
		});		
		return authorities;
	}
	
	
	/**
	 * 사용자를 인증하는 데 사용된 암호를 반환합니다.
	 */
	@Override
	public String getPassword() {
		return user.getPassword();
	}

	/**
	 * 사용자를 인증하는 데 사용된 사용자 이름을 반환합니다. null을 반환할 수 없습니다.
	 */
	@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() {
		//우리 사이트 1년동안 회원이 로그인을 안하면!! 휴먼 계정으로 하기로 함.
		//현재시간-로긴시간=>1년을 초과하면 return false;
		return true;
	}

	
	

}

 

PricipalDetailsService

package com.cos.jwt.auth;

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;

import com.cos.jwt.model.User;
import com.cos.jwt.repository.UserRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;


@Service
@RequiredArgsConstructor
@Slf4j
public class PricipalDetailsService implements UserDetailsService{
	
	private final UserRepository userRepository;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User userEntity=userRepository.findByUsername(username);
		if(userEntity==null) {
			throw new UsernameNotFoundException("아이디 혹은 비밀번호가 일치하지 않습니다.");			
		}
		
		log.info("PrincipalDetailService 의 loadUse  userEntity : =>" +userEntity);
		return new PrincipalDetails(userEntity);
	}	
}

 

 

 

 

 

7. JwtProperties  ,   JwtAuthenticationFilter , JwtAuthorizationFilter  생성

 

JwtProperties 토큰 설정값

package com.cos.jwt.jwt;

public interface JwtProperties {
	String SECRET = "test1234!@#$"; // 우리 서버만 알고 있는 비밀값
	int EXPIRATION_TIME = 10*24*60*60*1000; //10일*24시간*60분*60초 (1/1000초) =864,000,000(10일)
	String TOKEN_PREFIX = "Bearer ";
	String HEADER_STRING = "Authorization";
}

 

 

JwtAuthenticationFilter  로그인시 토큰 생성
 

package com.cos.jwt.jwt;

import java.io.IOException;
import java.util.Date;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.cos.jwt.auth.PrincipalDetails;
import com.cos.jwt.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**1.세션 방식
 * 유저네임, 패스워드 로그인 정상
 * 서버쪽 세션 ID 생성
 * 클라이언트 쿠키 세션ID를 응답
 * 
 * 
 * 요청할 때마다 쿠키값 세션 ID를 항상 들고 서버쪽으로 요청하기 때문에
 * 서버는 세션 ID가 유효한지 판단해서 유효하면 인증이 필요한 페이지로 접근하게 하면 되요.
 * 
 *
 *
 *2.JWT 토큰 방식
 *유저네밈 , 패스워드 로그인 정상
 *JWT 토큰을 생성
 *클라이언트 쪽으로 JWT토큰을 응답
 *
 *
 *요청할 때마다 JWT 토큰을 가지고 요청
 *서버는 JWT 토큰이 유효한지를 판단 (필터를 만들어야 함)
 *
 *
 *
 *3. 처리 과정
 *
 *1) login(/login)요청을 하면 JSON 데이터 username, password 을  ObjectMapper 이용하여 User로 받는다.
  2) Authentication authentication=authenticationManager.authenticate(authenticationToken) 처리 실행함으로 서
     loadUserByUsername() 함수가 실행된 후 정상이면 authentication 이 리턴됨.	
	 PrincipalDetailsService 가 호출  loadUserByUsername() 함수 실행됨.
			
  3)PrincipalDetails를 세션에 담고(권한관리를 위해서)
			
  4)JWT토큰을 만들어서 응답해주면 됨.
 *
 *
 */

//스프링 시큐리티에서 UsernamePasswrodAuthenticationFilter 가 있음.
//login 요청해서 username, passwrod 전송하면 (post)
//UsernamePasswordAuthenticationFilter 동작을 함.
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

	private final AuthenticationManager authenticationManager;
	

	//login 요청을 하면 로그인 시도를 위해서 실행되는 함수=> /login
	// Authentication 객체 만들어서 리턴 => 의존 : AuthenticationManager
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {
		log.info("JwtAuthenticationFilter : 로그인 시도중 ");
		
	
		try {

			//JSON 형태의 데이터를 받아와서 User 객체에 넣는다.
			// request에 있는 username과 password를 파싱해서 자바 Object로 받기
			ObjectMapper objectMapper=new ObjectMapper();
			User user =objectMapper.readValue(request.getInputStream(), User.class);
			
						
			UsernamePasswordAuthenticationToken  authenticationToken=
					new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
			
			//PrincipalDetailsService 의 loadUserByUsername() 함수가 실행된 후 정상이면 authentication 이 리턴됨.
			//DB에 있는 username 과 passwrod 가 일치한다.
			Authentication authentication=authenticationManager.authenticate(authenticationToken);
			
			
			//authentication 객체가 session 영역에 저장됨  => 로그인이 되었다는 뜻.
			PrincipalDetails principalDetails=(PrincipalDetails)authentication.getPrincipal();		
			
			log.info(principalDetails.getUser().getUsername());	//로그인 정상적으로 되었다는 것.

			//authentication 객체가 session 영역에 저장을 해야하고 그 방법이 return 해주면 됨.
			//리턴의 이유는 권한 관리를 security 가 대신 해주기 때문에 편하력하는 것임.
			//굳이 JWT 토큰을 사용하면서 세션을 만들 이유가 없음. 근데 단지 권한 처리때문에 session 넣어 줌
								
			return authentication;
		} catch (IOException e) {
			e.printStackTrace();			
		}
		return null;
	}
	
	
	
	/**
	 *  인증이 안되면 401 에러 난다. 따라서  해 정상적으로 인증이 되었으면
	 *  successfulAuthentication 메소드를 통과하기 때문에 successfulAuthentication 메소드에서
	 *  JWT 토큰을 발행 시킨다.
	 *{
		    "timestamp": "2022-06-18T09:22:16.260+00:00",
		    "status": 401,
		    "error": "Unauthorized",
		    "message": "Unauthorized",
		    "path": "/login"
		}
	 * 
	 * 
	 * 
	 * */	
	// ★★ successfulAuthentication 메서드는 attemptAuthentication 실행 후 인증이 정상적으로 되었으며 successfulAuthentication 함수가 실행됨.
	//JWT 토큰을 만들어서 request 요청한 사용자에게 JWT 토큰을 respons 해주면 됨.
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException, ServletException {
		log.info("successfulAuthentication 실행됨 : 인증이 완료되었다는 뜻임");

		PrincipalDetails principalDetails=(PrincipalDetails)authResult.getPrincipal();	
		
		//RSA방식은 아니구 Hash 암호방식
		String jwtToken=JWT.create()
				.withSubject(principalDetails.getUsername())
				.withExpiresAt(new Date(System.currentTimeMillis()+(JwtProperties.EXPIRATION_TIME)))  //토큰 만료시간 
				.withClaim("id", principalDetails.getUser().getId())
				.withClaim("username", principalDetails.getUser().getUsername())
				.sign(Algorithm.HMAC512(JwtProperties.SECRET.getBytes()));		
	
		/**
		다음과 같은 토큰을 헤더 Authorization 에 반환
			BearereyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjb3PthqDtgbAiLCJpZCI6MSwiZXhwIjoxNjU1NTYzOTc5LCJ1c2VybmFtZSI6InNzYXJsIn0.9jpWJQF8X21tj_VSNlH_ybtIBUqHxJWoUAuPOG4qFDlEoeWY1SS_UJOp1clz92wNJG51EkcTPK1nVavAd1mGqA
		*/
		response.addHeader(JwtProperties.HEADER_STRING, JwtProperties.TOKEN_PREFIX+jwtToken);	
	}
	
	
	
	
	

	
	
	
}

 

 

JwtAuthorizationFilter

package com.cos.jwt.jwt;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cos.jwt.auth.PrincipalDetails;
import com.cos.jwt.model.User;
import com.cos.jwt.repository.UserRepository;

import lombok.extern.slf4j.Slf4j;

//시큐리티가 filter 가지고 있는데 그 필터중에서 BasicAuthenticationFilter 라는 것이 있음.
//권한이나 인증이 필요한 특정 주소를 요청했을 때 위 필터를 무조건 타게 되어 있음.
//만약에 권한이 인증이 필요한 주소가 아니라면 이 필터를 안 탄다.
@Slf4j
public class JwtAuthorizationFilter extends BasicAuthenticationFilter{

	private UserRepository userRepository;
	
	public JwtAuthorizationFilter(AuthenticationManager authenticationManager,UserRepository userRepository) {
		super(authenticationManager);
		this.userRepository=userRepository;
	}

	
	//인증이나 권한이 필요한 주소요청이 있을 때 해당 필터를 타게 됨.
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		log.info("인증이나 권한이 필요한 주소 요청이 됨");
		
		String jwtHeader=request.getHeader(JwtProperties.HEADER_STRING);		
		//header가 있는지 확인		
		if(jwtHeader==null|| !jwtHeader.startsWith(JwtProperties.TOKEN_PREFIX)){
			chain.doFilter(request, response);
			return;
		}
	
		 //헤더 Authorization 의 값 "Bearer " 제거 처리 
		String jwtToken=request.getHeader(JwtProperties.HEADER_STRING).replace(JwtProperties.TOKEN_PREFIX, "");				

		
		// 토큰 검증 (이게 인증이기 때문에 AuthenticationManager도 필요 없음)
		// 내가 SecurityContext에 집적접근해서 세션을 만들때 자동으로 UserDetailsService에 있는 loadByUsername이 호출됨.
		String username=JWT.require(Algorithm.HMAC512(JwtProperties.SECRET.getBytes())).build().verify(jwtToken).getClaim("username").asString();

				
		
		//서명이 정상으로 됨
		if(username!=null) {
			User userEnity=userRepository.findByUsername(username);		
	
			// 인증은 토큰 검증시 끝. 인증을 하기 위해서가 아닌 스프링 시큐리티가 수행해주는 권한 처리를 위해 
			// 아래와 같이 토큰을 만들어서 Authentication 객체를 강제로 만들고 그걸 세션에 저장!
			PrincipalDetails principalDetails=new PrincipalDetails(userEnity);
			Authentication authentication=
					new UsernamePasswordAuthenticationToken(
							principalDetails,  //나중에 컨트롤러에서 DI해서 쓸 때 사용하기 편함.
							null,// 패스워드는 모르니까 null 처리, 어차피 지금 인증하는게 아니니까!!
							principalDetails.getAuthorities());		
						
			//강제로 시큐리티의 세션에 접근하여 Authentication 객체를 저장.
			SecurityContextHolder.getContext().setAuthentication(authentication);		
		}
		
		chain.doFilter(request, response);
		
	}
	
	
	
	
	
	
}

 

 

 

8. PostMan 테스트

 

1) 회원가입

 

2) DB  등록 확인

 

 

3) 로그인 (( 헤더에서 토큰값을 반환)

 

 

4) Headers 에 Authorization 에  키값에  로그인후 반환된 토큰값을 입력후

http://localhost:8080/api/v1/user,   http://localhost:8080/api/v1/manager,   http://localhost:8080/api/v1/admin 별로 테스트 확인

 

 

 

 

 

소스 :

https://github.com/braverokmc79/jwt1

https://github.com/codingspecialist/Springboot-Security-JWT-Easy

 

참조 및 강의

메타코딩 - Springboot - 시큐리티 특강

https://www.youtube.com/playlist?list=PL93mKxaRDidERCyMaobSLkvSPzYtIk0Ah

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

행복은 마음먹기에 달려 있다. -에이브러햄 링컨

댓글 ( 4)

댓글 남기기

작성

스프링 목록    more