BE/Spring

[Spring Security] JWT - 4. JWT 로그인 및 권한 처리

멍목 2022. 6. 19. 18:56
반응형

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

https://inf.run/tcLk

 

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

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

www.inflearn.com


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

1) 컨트롤러에서 권한 테스트 할 함수 만들기

	// user,manager,admin 권한만 접근 가능
    @GetMapping("/api/v1/user")
    public String user(Authentication authentication){
        PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
        System.out.println("api/v1/user: " + 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";
    }

 

 

2) JwtAuthorizationFilter 생성(권한 처리하는 곳)

package com.cos.jwt.security1.config.jwtConfig;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.cos.jwt.security1.Repository.UserRepository;
import com.cos.jwt.security1.config.jwtAuth.PrincipalDetails;
import com.cos.jwt.security1.model.User;
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 javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


// 시큐리티가 filter를 가지는데, 필터중에 BasicAuthenticationFilter 가 있음.
// 권한이나 인증이 필요한 특정 주소를 요청했을 때, 위의 필터를 무조건 탄다.
// 만약 권한이나 인증이 필요한 주소가 아니라면 이 필터를 타지 않는다.
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 {
        System.out.println("인증이나 권한이 필요한 주소");

        String jwtHeader = request.getHeader("Authorization");
        System.out.println("jwtHeader : " + jwtHeader);

        // JWT 토큰을 검증해서 정상적인 사용자인지 확인
        // jwtHeader가 없거나 Bearer로 시작하는 게 아니면 정상적인 토큰이 아니라고 판단
        if(jwtHeader == null || !jwtHeader.startsWith("Bearer")){
            chain.doFilter(request, response);
            return;
        }

        // 받은 JWT헤더에서 Bearer을 없앰
        String jwtToken = request.getHeader("Authorization").replace("Bearer ", "");

        // jwt토큰 확인 작업
        String username =
                JWT.require(Algorithm.HMAC512("cos")).build().verify(jwtToken).getClaim("username").asString();

        // 서명이 정상적으로 됨
        if(username != null){
            User userEntity = userRepository.findByUsername(username);
            PrincipalDetails principalDetails = new PrincipalDetails(userEntity);

            // JWT 토큰 서명을 통해서 서명이 정상적이라면 Authentication 객체를 만들어준다.
            Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities());

            // 강제로 시큐리티의 세션에 접근하여 Authentication 저장
            SecurityContextHolder.getContext().setAuthentication((authentication));
        }
        chain.doFilter(request, response);
    }
}

 

3) 결과 확인

- 로그인한 사용자의 권한 : ROLE_USER

 

 

- user 주소로 접근 : 접근 가능

 

 

- admin 주소로 접근 : 권한 X (403에러)

 

반응형