Be ready to study forever - 개발자 꿈나무

[Spring Security] JWT적용 본문

Programming/Spring

[Spring Security] JWT적용

루눌룹 2020. 8. 23. 19:02

1. build.gradle에 dependancies 추가

dependencies{
	//...
    implementation 'org.springframework.boot:spring-boot-starter-security'//스프링 시큐리티
    implementation 'io.jsonwebtoken:jjwt-api:0.10.7'//jjwt

    runtime 'io.jsonwebtoken:jjwt-impl:0.10.7'//jjwt
    runtime 'io.jsonwebtoken:jjwt-jackson:0.10.7'//jjwt
}

 

2. JWT를 생성 및 조회할 클래스를 생성한다 추후에 필터나 로그인 후에 발행할 때 사용

public class JwtUtil {

    private Key key;

    public JwtUtil(String secret){//외부에서(키값음 property.yml에 넣어놈) 시크릿 키 주입
        this.key = Keys.hmacShaKeyFor(secret.getBytes());

    }

    public String createToken(long id, String name) {//JWT생성
        String token = Jwts.builder()
                .claim("userId",id) //키값과 벨류로 쌍으로 묶임(payload에 들어갈 부분)
                .claim("name",name) //키값과 벨류로 쌍으로 묶임(payload에 들어갈 부분)
                .signWith(key, SignatureAlgorithm.HS256)//고유한 키값을 해싱
                .compact();
        return token;
    }

    public Claims getClamins(String token) {//JWT조회(?)
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token)//싸인이 포함된 jwt = jws
                .getBody();
        return claims;
    }
}

 

3. BasicAuthenticationFilter를 상속받아 JWT를 사용한 필터를 만듬

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    private JwtUtil jwtUtil;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtUtil jwtUtil) {//JwtUtil을 사용하기 위해서 생성자로 받음
        super(authenticationManager);
        this.jwtUtil = jwtUtil;
    }

    @Override//doFilterInternal은 BasicAuthenticationFilter를 override함
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain
    ) throws IOException, ServletException {
        Authentication authentication = getAuthentication(request);
        if(authentication != null){
            SecurityContext context = SecurityContextHolder.getContext();
            context.setAuthentication(authentication);
        }
        chain.doFilter(request, response);// 체인을 통해 다음작업으로 계속 연결됨
    }

    private Authentication getAuthentication(HttpServletRequest request){
        String token = request.getHeader("Authorization");//header안에 있는 Authentication 값은 없을수도 있기 때문에 예외처리가 필요함

        if(token == null){
            return null;
        }
        //header는 Authorization :Bearer fsdgssdgsdgsd32f3.3f233r32r53....
        //와 같이 되어 있기 때문에 Bearerㄹ르 서브스트링으로 제거해주고 넘겨야한다
        Claims claims = jwtUtil.getClamins(token.substring("Bearer ".length()));

        Authentication authentication = new UsernamePasswordAuthenticationToken(claims, null);

        return authentication;
    }
}

 

4.시큐리티 설정에 JWT를 이용한 필터를 추가 addFilter(filter)부분

@Configuration//설정 자바파일에는 이 어노테이션을 붙어야함
@EnableWebSecurity//웹 시큐리티를 사용 가능하게 설정합
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter{//자바기반 설정으로 Spring Security를 사용할 수 있다 WebSecurityConfigurerAdapter를상속받아 빠르게 설정이 가능하다

    @Value("${jwt.secret}")//깃허브등에 올릴때 외부에 들어나지 않도록 properties.yml에서 가져옴
    private String secret;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       Filter filter = new JwtAuthenticationFilter(authenticationManager(),jwtUtil());//BasicAuthenticationFilter을 상속받음

        http.formLogin().disable()//디폴트 로그인 폼을 없앰
            .csrf().disable() //csrf인증 기능을 끔
            .cors().disable() //cors기능을 끔
                .headers().frameOptions().disable()//iframe 차단기능을 끔
            .and() //and는 .header에서 http로 나오기 위해 사용
                .addFilter(filter)//필터만들어서 적용
            .sessionManagement()//세션관리 설정
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);//서버에 값을 세션값을 저장하지 않고 stateless로 설정함
    }

    @Bean//BCryptPasswordEncoder빈 등록
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean//JwtUtil 빈 등록
    public JwtUtil jwtUtil(){
        return new JwtUtil(secret);
    }
}

properties.yml에 적용도니 jwt의 ket값 @value("$jwt.secret")으로 찾아옴

jwt:
  secret: goodlekkfekfosd@424fe4oj5ojofjsdifjhij3lkfjl3jlkrjldk1252f

 

5.JWT토큰을 에서 이름값 가져오기

@RestController
public class ReviewController {

    @Autowired
    ReviewService reviewService;

    @PostMapping("restaurant/{RestaurantId}/reviews")//Authentication을 필터를 만들어주었기 때문에 가능
    public ResponseEntity<Object> create(Authentication authentication, @PathVariable Long RestaurantId, @Valid @RequestBody Review resource) throws URISyntaxException {
        Claims claims = (Claims) authentication.getPrincipal();//Claims로 형변환
        String name = claims.get("name",String.class);//반환받을 타입을 String.class로 설정
        Integer score = resource.getScore();
        String description = resource.getDescription();
        Review review = reviewService.addReview(RestaurantId,name, description, score);

        URI location = new URI("/restaurant/"+RestaurantId+"/reviews/"+review.getId());
        return ResponseEntity.created(location).body("{}");
    }
}

 

더 공부가 필요한 부분....

https://webfirewood.tistory.com/m/115?category=694472

 

'Programming > Spring' 카테고리의 다른 글

Maven  (0) 2020.07.20
Comments