본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Spring framework/Spring boot

[SpringBoot] Spring Security jwt 연동 하기 - 2023

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2023. 4. 7.

 

스프링 부트 환경에서 시큐리티와 JWT를 연동하는 방법 입니다.

이미 수많은 글들이 존재하지만 제 스스로가 이해하기 쉽도록 정리를 한번 해 보았습니다.

먼저 필요한 라이브러리는 3종류 입니다.

* maven 기준

<!-- 시큐리티 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- JWT -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>

 

기능은 크게 2가지로 구분지어 적용 할 수 있습니다.

 

1. JWT 설정

2. 시큐리티 설정

 

시큐리티는 기본적으로 서버의 자원을 활용하여 로그인 여부를 관리하고 판단 합니다.

사용자가 로그인하거나 정보를 바꾸면 서버 내부의 세션(session)을 생성하여 관리를 합니다.

그러므로 이러한 시큐리티에 JWT를 적용 하기 위해서는 기본적인 로그인에 대한 개념, 서버 자원인 세션이 무엇인지,

JWT를 만들어서 클라이언트에서 어떻게 사용하는지 등에 대해서 알고 있어야 합니다.

 


 

#1. JWT 설정

JWT설정은 2가지로 나누어 볼 수 있습니다.

 1) 데이터를 받아서 토큰을 만들거나 분석 하는 기능

 2) 사용자의 요청을 검증(filter, validate)하는 기능

 

먼저 토큰을 만들고 분석하는 클래스 입니다.

* 파일이름 : JWT토큰프로바이더.class

import java.util.Base64;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class JWT토큰프로바이더 {
	
    public static String HTTP헤더에담을키값 = "Authorization";
    private String 비밀키 = "myJWTKey";
    private long 유지시간 = 60 * 60 * 1000L;  //토큰 유효시간 : 60분

    private final UserDetailsService 유저서비스;
    
    public JWT토큰프로바이더(UserDetailsService 유저서비스){
    	this.유저서비스 = 유저서비스;
    }

    //객체 초기화, secretKey를 Base64로 인코딩한다.
    @PostConstruct
    protected void 비밀키인코딩() {
    	비밀키 = Base64.getEncoder().encodeToString(비밀키.getBytes());
    }

    // JWT 토큰 생성 
    public String 토큰발행(String userPk, List<String> roles) {
        Claims claims = Jwts.claims().setSubject(userPk); // JWT payload 에 저장되는 정보단위, 보통 여기서 user를 식별하는 값을 넣는다.
        claims.put("roles", roles); // 정보는 key / value 쌍으로 저장된다.
        Date now = new Date();
        return Jwts.builder()
                .setClaims(claims) //정보 저장
                .setIssuedAt(now) //토큰 발행 시간
                .setExpiration(new Date(now.getTime() + 유지시간)) //만료시간
                .signWith(SignatureAlgorithm.HS256, 비밀키)  //사용할 암호화 알고리즘과 signature 에 들어갈 secret값 세팅
                .compact();
    }

    //JWT 토큰에서 인증 정보 조회
    public Authentication 권한조회(String token) {
        UserDetails userDetails = 유저서비스.loadUserByUsername(this.사용자정보확인(token));
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }

    // 토큰의 유효성 + 만료일자 확인
    public boolean 토큰검사(String jwtToken) {
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(비밀키).parseClaimsJws(jwtToken);
            System.out.println(claims );
            return !claims.getBody().getExpiration().before(new Date());
        } catch (Exception e) {
        	e.printStackTrace();
            return false;
        }
    }
    
    //토큰에서 회원 정보 추출
    private String 사용자정보확인(String token) {
        return Jwts.parser().setSigningKey(비밀키).parseClaimsJws(token).getBody().getSubject();
    }    
}

 

해당 클래스는 토큰을 발행하고, 받은 토큰 값을 분석하는 클래스 입니다.

컴포넌트(Component)로 관리하기 때 문에 해당 클래스는 어디서든 의존성을 주입받아 사용 할 수 있습니다.

위 클래스에서 "토큰발행" 메소드는 사용자의 로그인 행위가 올바르면 토큰값을 전달하여 주는 메소드 입니다.

"권한조회" "토큰검사" 메소드는 사용자가 로그인이 된 상태에서 권한(authentication)이 필요한 페이지로 이동 할 때 동작을 하는 메소드 입니다.

 

데이터를 처리하는 클래스가 완성 되었으므로 이제 사용자의 요청을 검증하는, 가로채는 클래스를 만들어 줍니다.

* 파일이름 : JWT토큰필터.class

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

@Component
public class JWT토큰필터 extends GenericFilterBean {
	
	private JWT토큰프로바이더 provider;
	
	public JWT토큰필터(JWT토큰프로바이더 provider) {
		this.provider = provider;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String token = ((HttpServletRequest) request).getHeader(JWT토큰프로바이더.HTTP헤더에담을키값);
        //유효한 토큰인지 확인합니다.
        if (token != null && provider.토큰검사(token)) {
            // 토큰이 유효하면 토큰으로부터 유저 정보를 받아옵니다.
            Authentication authentication = provider.권한조회(token);
            //SecurityContext 에 Authentication 객체를 저장합니다.
            SecurityContextHolder.getContext().setAuthentication(authentication);
            System.out.println(authentication);
        }
        chain.doFilter(request, response);
	}

}

 

위 클래스는 필터형태의 클래스 입니다.

스프링부트에서 필터란 컨트롤러 역할을 하는 메소드에게 요청이 전달되기 전에 행동을 하는 기능 입니다.

스프링부트에서 시큐리티는 기본적으로 서버 자원인 세션(session)을 통하여 로그인 여부를 검증 하는데,

이러한 검증 방법을 JWT로 바꾸어 주기 위해서는 JWT 값을 통해 동작하는 필터클래스를 만들어 주어야 합니다.

 

여기까지 이제 JWT와 관련된 기능 이였습니다.

그러면 이제 시큐리티(security)의 기본설정을 해 주고 해당 설정에서 JWT를 추가하는 방법 입니다.

 


 

#2. 시큐리티 설정

시큐리티는 3개의 설정이 필요 합니다.

1. 로그인 요청을 받아 DB에서 데이터를 조회한 뒤 결과를 전달하는 서비스 기능

2. 위 서비스에서 사용자의 아이디, 비밀번호를 통하여 데이터베이스 결과를 매핑(ORM)하는 유저 기능

3. 접근 가능한 요청, 불가능한 요청 및 시큐리티의 전반적인 기능을 담당하는 컨피그 기능

 

1번 기능을 만들기 전에 db결과를 매핑(ORM)하는 클래스인 2번부터 만들어 줍니다.

* 파일이름 : 시큐리티유저.class

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

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

public class 시큐리티유저 implements UserDetails {

	private static final long serialVersionUID = 1L;

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		List<GrantedAuthority> list = new LinkedList<GrantedAuthority>();
		list.add(new SimpleGrantedAuthority("auth1"));
		list.add(new SimpleGrantedAuthority("auth2"));
		return list;
	}

	@Override
	public String getPassword() {
		return "$2a$10$SDBxd18/9SovlON7h/HewOwTe/drGLIx/UV0G0k91qLRWnGz0VoR.";  //1234
	}

	@Override
	public String getUsername() {
		// TODO Auto-generated method stub
		return "admin";
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return true;
	}

}

 

위 코드는 아이디, 비밀번호 및 권한 값이 하드코딩 되어있는 클래스 입니다.

이렇게 만들어진 클래스는 JPA, MyBatis 같은 프레임워크에서 결과를 반환 할 때 결과 클래스로 사용하면 됩니다.

또한 결과값이 지금은 하드코딩 되어 있지만, JPA, MyBatis 같은 프레임워크에 실제 적용하려면 아래처럼 매핑할 변수를 클래스 내부에 추가한 뒤 고쳐 주어야 합니다.

//생략..
public class 시큐리티유저 implements UserDetails {

    private static final long serialVersionUID = 1L;
    private String userId;  //요렇게....db에 매핑할 이름
    private String password;  //요렇게....db에 매핑할 이름
    private List<GrantedAuthority> userAuth;  //요렇게....db에 매핑할 이름

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		//List<GrantedAuthority> list = new LinkedList<GrantedAuthority>();
		//list.add(new SimpleGrantedAuthority("auth1"));
		//list.add(new SimpleGrantedAuthority("auth2"));
		return userAuth;   //반환 값은 db결과값이 나오도록, 또는 원하는 권한 형태 조립
	}

	@Override
	public String getPassword() {
		//return "$2a$10$SDBxd18/9SovlON7h/HewOwTe/drGLIx/UV0G0k91qLRWnGz0VoR.";
		return password; //반환 값은 db결과값이 나오도록
	}

	@Override
	public String getUsername() {
		//return "admin";
		return userId; //반환 값은 db결과값이 나오도록
	}
	//생략....
}

 

데이터베이스 조회를 매핑하는 클래스가 만들어 졌으므로 다음으로 로그인 요청을 받아 DB에서 데이터를 조회한 뒤 결과를 전달하는 서비스 기능을 만들어 줍니다.

* 파일이름 : 시큐리티서비스.class

import org.springframework.security.core.userdetails.User;
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
public class 시큐리티서비스 implements UserDetailsService {

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

		시큐리티유저 user = new 시큐리티유저(); // 요기에 db에 갔다온 결과가 필요 합니다. 유저클래스는 DTO객체 입니다.
		UserDetails build = null;
		
		try {
			User.UserBuilder userBuilder = User.withUsername(username).password(user.getPassword());
			userBuilder.authorities(user.getAuthorities());
			build = userBuilder.build();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return build;
	}

}

 

많이 보던 시큐리티 서비스 클래스 입니다.

해당 클래스에서는 지금은 시큐리티유저 클래스가 new로 만들어 지고 있으나, 사용중인 데이터베이스 프레임워크에 맞게 기능을 바꾸어 주면 되겠습니다.

 

여태껏 만들어준 기능들은 시큐리티 설정을 위한 일종의 아이템(item) 이라고 볼 수 있습니다.

위 아이템(item)들을 이제 기능과 역할에 맞게 동작 하도록 설정을 해 주도록 합니다.

먼저 첫번째 설정 입니다.

import org.springframework.context.annotation.Configuration;

@Configuration
public class 시큐리티설정 {

	시큐리티서비스 service;	
	JWT토큰필터 filter;
	JWT토큰프로바이더 provide;
	
	public 시큐리티설정(JWT토큰필터 filter, JWT토큰프로바이더 provide, 시큐리티서비스 service){
		this.filter = filter;
		this.provide = provide;
		this.service = service;
	}
}

 

3개 클래스가 생성자를 통하여 의존성을 주입받고 있습니다.   * new로 선언할 이유가 없습니다!!

"JWT토큰필터.class"를 주입받아 기존의 세션(session) 형식의 로그인 정보관리를 JWT 방식으로 바꾸어 줄 예정 입니다.

"JWT토큰프로바이더.class"를 주입받아 로그인이 성공한 경우 사용자에게 JWT토큰을 전달 해줄 예정 입니다.

마지막으로 "시큐리티서비스.class"는 굳이 선언하지 않아도 되지만, 차후에 로그인과 관련된 추가 기능을 달아줄 경우 해당 클래스에 기능을 붙이면 되겠습니다.

 

"시큐리티서비스.class" 클래스는 에노테이션인 ServiceUserDetailsService를 상속하여 이미 스프링 시큐리티에서 해당 클래스를 로그인 요청이 들어오면 스스로 알아서 동작하게 관리를 해 주고 있기 때 문에 굳이 가져오지 않아도 됩니다.

 

다음 설정은 "시큐리티서비스.class" 클래스가 사용자의 비밀번호를 받아서 암호화를 하기위한 객체선언 입니다.

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class 시큐리티설정 {

	//생략..

	/*
	 * 비밀번호를 암호화하는 Bean 입니다. 
	 * 해당 인코더를 설정하지 않으면 만들어준 시큐리티서비스(service)에서 비밀번호 암호화 할 때 오류가 발생 합니다.
	 * */
	@Bean
	PasswordEncoder passwordEncoder() {  	
		return new BCryptPasswordEncoder();  
	}
	    

}

 

빈(Bean) 에노테이션을 활용하여 단순하게 인코딩 관련된 클래스를 반환 해 주기만 하더라도 스프링 부트에서는 사용자의 암호와 관련된 데이터를 알아서 암호화 하여 줍니다.

 

다음으로 권한 없이 접근을 하기위한 페이지 설정 입니다.

import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;

@Configuration
public class 시큐리티설정 {

	//생략..

	/*
	 * 따로 무슨 행동을 하지 않아도 허용 해 주는 주소 모음 입니다.
	 * */
    @Bean
    WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/" );
    }    	
	    
}

 

css라는 요청, js라는 요청 및 일반 접근(/) 에 대해서는 시큐리티가 검사하지 않고 허용 하겠다는 의미 입니다.

위 설정을 하지 않으면 해당 웹사이트는 누구도 접근을 못하는 페이지가 되어 버립니다.

드디어 대망의 최종 설정구간 입니다.

@Configuration
public class 시큐리티설정 {
	

	시큐리티서비스 service;	
	JWT토큰필터 filter;
	JWT토큰프로바이더 provide;
	
	public 시큐리티설정(JWT토큰필터 filter, JWT토큰프로바이더 provide, 시큐리티서비스 service){
		this.filter = filter;
		this.provide = provide;
		this.service = service;
	}
    
	//생략..    
    
    
    /*
     * 시큐리티설정, jwt 설정을 하여 줍니다.
     * */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    	
    	//#1. 권한이 필요한 대상입니다.
        http.authorizeRequests()
        	.antMatchers("/test").authenticated()
        	.antMatchers("/test2").authenticated()
        	;
    	
        //#2. 세션을 쓰지 않습니다.
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        //#3. JWT 필터를 쓰겠다고 설정하여 줍니다.
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
        
        //#4. 사용자의 로그인 행동에 대한 정의 입니다.
		http.formLogin()
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")        
        .successHandler((request, response, auth)->{  //로그인 성공시 행동을 정의 합니다.
			String ip = request.getRemoteAddr();
			String user_id = auth.getName();
			
			System.out.println("login ok : "+ip + "" + user_id);
			
			response.setCharacterEncoding("UTF-8");
			response.setHeader("Content-Type", "application/download; UTF-8");
			String token = provide.토큰발행(user_id, auth.getAuthorities().stream().map(arg-> arg.getAuthority()).collect(Collectors.toList()));
			response.getWriter().write("{\"result\" : \""+token+"\" }");
			
		})       
        .failureHandler((request, response, auth)->{  //로그인 실패시 행동을 정의 합니다.
			String ip = request.getRemoteAddr();
			String user_id = request.getParameter("username");
			
			System.out.println("login fail : "+ip + "" + user_id);
			
			response.sendRedirect("/");
		}) .permitAll();
		
		//#5.csrf 설정을 off 합니다.
		http.csrf().disable();
    	
    	return http.build();
    }
    
}

 

코드에 주석을 붙여 놓았습니다.

눈여겨 보아야 할 구간인 #3번은 주입받은 "JWT토큰필터.class" 필터형식의 클래스를 추가하여 주면 됩니다.

 

#4번 설정의 첫번째 구간은 로그인에 대한 선언 입니다.

loginProcessingUrl 메소드는 브라우저에서 로그인 버튼을 누르면 보내는 주소를 의미 합니다.

사용자가 "http://x.x.x.x/login" 이라는 요청을 보내게 되면 시큐리티 설정에 의해서 자동으로 우리가 만들어준 "시큐리티서비스.class"에 존재하는 "loadUserByUsername" 메소드를 동작 시키게 됩니다.

 

이때 브라우저에서 아이디와 비밀번호는 아래 2개의 메소드에 전달된 이름과 같아야 합니다.

아이디 : username

비밀번호 : password

 

위 2개의 값은 아래 메소드를 통해 바꿀 수 있습니다.

usernameParameter("원하는 아이디 파라미터이름")
passwordParameter("원하는 비밀번호 파라미터이름")    

 

다음으로 "시큐리티서비스.class"에서 "loadUserByUsername" 메소드가 사용자의 정보가 맞다고 결과값을 반환하게 되면 #4번에 설정 해준 successHandler 메소드가 동작하게되고, 그렇지 않다면 failureHandler 메소드가 동작하게 됩니다.

 

"시큐리티설정.class" 클래스에서 따로 "시큐리티서비스.class"호출하거나 메소드를 부르지 않았음에도 시큐리티에서 이러한 부분을 알아서 동작시켜 주기 때 문에 이처럼 기능을 분리할 수가 있습니다.

 

성공을 하게되면 이제 아래처럼 JWT토큰값을 발행해 주면 됩니다.

response 객체에 write 메소드를 통해 결과값을 json 또는 xml 및 단순 문자열 등으로 전달해 주도록 합니다.

* 원하는 데로 바꾸어도 됩니다.

 

#5번은 CSRF 설정 입니다.

CSRF는 POST 요청에 대해서 유요한 키 값 여부를 확인하는 기능으로, 악성코드에 대비하는 기능이라 할 수 있습니다.

csrf 설정을 disable 하지 않으면 post 요청에 대해서 403 오류가 계속해서 나게 됩니다.

해당 설정은 필요한 경우에 찾아서 적용하면 되겠습니다.

 

위 내용에 대한 최종 "시큐리티설정.class" 코드 입니다.

* 파일이름 : 시큐리티설정.class

import java.util.stream.Collectors;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class 시큐리티설정 {
	

	시큐리티서비스 service;	
	JWT토큰필터 filter;
	JWT토큰프로바이더 provide;
	
	public 시큐리티설정(JWT토큰필터 filter, JWT토큰프로바이더 provide, 시큐리티서비스 service){
		this.filter = filter;
		this.provide = provide;
		this.service = service;
	}

	/*
	 * 비밀번호를 암호화하는 Bean 입니다. 
	 * 해당 인코더를 설정하지 않으면 만들어준 시큐리티서비스(service)에서 비밀번호 암호화 할 때 오류가 발생 합니다.
	 * */
	@Bean
	PasswordEncoder passwordEncoder() {  	
		return new BCryptPasswordEncoder();  
	}
	    
	/*
	 * 따로 무슨 행동을 하지 않아도 허용 해 주는 주소 모음 입니다.
	 * */
    @Bean
    WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/" );
    }    	
    
    /*
     * 시큐리티설정, jwt 설정을 하여 줍니다.
     * */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    	
    	//#1. 권한이 필요한 대상입니다.
        http.authorizeRequests()
        	.antMatchers("/test").authenticated()
        	.antMatchers("/test2").authenticated()
        	;
    	
        //#2. 세션을 쓰지 않습니다.
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        //#3. JWT 필터를 쓰겠다고 설정하여 줍니다.
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
        
        //#4. 사용자의 로그인 행동에 대한 정의 입니다.
		http.formLogin()
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")        
        .successHandler((request, response, auth)->{  //로그인 성공시 행동을 정의 합니다.
			String ip = request.getRemoteAddr();
			String user_id = auth.getName();
			
			System.out.println("login ok : "+ip + "" + user_id);
			
			response.setCharacterEncoding("UTF-8");
			response.setHeader("Content-Type", "application/download; UTF-8");
			String token = provide.토큰발행(user_id, auth.getAuthorities().stream().map(arg-> arg.getAuthority()).collect(Collectors.toList()));
			response.getWriter().write("{\"result\" : \""+token+"\" }");
			
		})       
        .failureHandler((request, response, auth)->{  //로그인 실패시 행동을 정의 합니다.
			String ip = request.getRemoteAddr();
			String user_id = request.getParameter("username");
			
			System.out.println("login fail : "+ip + "" + user_id);
			
			response.sendRedirect("/");
		}) .permitAll();
		
		//#5.csrf 설정을 off 합니다.
		http.csrf().disable();
    	
    	return http.build();
    }
}

 

최종 코드는 아래 zip 파일 또는 깃허브에서 받아볼 수 있습니다.

시큐리티-JWT 샘플.zip
0.01MB

 

https://github.com/TaeSeungRyu/sample/스프링시큐리티-JWT샘플

 

GitHub - TaeSeungRyu/sample

Contribute to TaeSeungRyu/sample development by creating an account on GitHub.

github.com

 

5개의 파일만 있으면 시큐리티와 JWT를 이처럼 간단하게 구성 할 수 있습니다.

JWT 값은 서버에서는 오직 생성과 검증을 합니다.

JWT 값은 브라우저에 존재하는 로컬스토리지(localStorage)나 세션스토리지(sessionStorage)에 저장한 뒤에 사용을 하며,

사용자가 로그아웃 행위를 하면 저장 장소에 내용을 제거해 주는 방식을 취하면 됩니다.

* 만약 이러한 JWT 값이 탈취당한 상황 이라면, 본인의 컴퓨터의 브라우저가 해킹 당했다는 뜻 이므로 침착하게 브라우저를 제거 후 재설치 하거나 KISA에 연락을..

 

이상으로 스프링부트에서 시큐리티와 jwt 연동 하기에 대해서 작성 해 보았습니다.

궁금한점 또는 틀린 부분은 언제든 연락 주세요! 👻

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글