Spring

jwt인증 403(forbidden)에러

Seung__Yong 2023. 3. 8. 09:32

CSRF TOKEN문제

스프링 시큐리티는 POST, PUT, DELETE등의 메소드 요청을 할 때 이전 페이지에서  발급된 CSRF토큰 정보를 체크하기 때문에 정보를 헤더로 넘겨줘야한다. 

1. CSRF Token발급 설정

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

2. csrf.disable()

[Springboot] CSRF Token 설정 시 Postman 테스트 방법(Spring Security) (tistory.com)

 

[Springboot] CSRF Token 설정 시 Postman 테스트 방법(Spring Security)

스프링 시큐리티는 POST, PUT, DELETE 등의 method를 요청할 때 이전 페이지에 발급된 CSRF토큰 정보를 체크하기 때문에 해당 정보를 header 로 넘겨주어야 처리가 된다. GET은 상관없음! 어쨋든 테스트 API

flowlog.tistory.com

 

 

권한 설정 시 에러( @PreAuthorize(hasRole("ADMIN")) )

public JwtTokenRes createToken(Authentication authentication, List<String> roles) {
		// roles = [ROLE_ADMIN, ROLE_USER, ROLE_MANAGER]
		String accessToken = Jwts.builder()
                .claim("roles",  roles.stream().collect(Collectors.joining(",")))) // 권한정보
                .setSubject(authentication.getName()) // 아이디
                .setExpiration(initializationAccessTime) // 만료기간
                .signWith(SignatureAlgorithm.HS256, key)
                .compact();
}

public Authentication getAuthentication(String accessToken){
        Claims claims = parseClaims(accessToken);

        if (claims.get("roles") == null){
            throw new RuntimeException("권한 정보가 없는 토큰입니다.");
        }
        Collection<? extends GrantedAuthority> authorities =
                Arrays.stream(claims.get("roles").toString().split(","))
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());

        UserDetails principal = new User(claims.getSubject(), "", authorities);
        return new UsernamePasswordAuthenticationToken(principal, "", authorities);
    }
  •  @PreAuthorize("hasRole('ADMIN')은 권한 정보 앞에 ROLE_ 접두사를 붙여서 체크합니다.
        -> hasRole을 사용했다면 권한정보는 "ROLE_ADMIN" 의 형태로 넣어줘야함
  •  @PreAuthorize(hasAuthirity("ADMIN"))을 사용했다면 "ADMIN"을 체크

 

  • 테스트 작성할 때 WithMockUser(roles = "ADMIN")을 사용하면 권한을 ROLE_ADMIN으로 만들어서 넘깁니다.
        -> hasAuthority("ADMIN")이라면 에러가 납니다.

 

  • 제가 실수했던 부분인데 저는 roles를 joinning하지않고 그냥 넘겼었습니다.

-> 권한이 하나라면 [ROLE_ADMIN] 요렇게 들어왔을거고 

     두 개라면 [ROLE_ADMIN,   ROLE_USER] 요렇게 들어왔던겁니다. 

 

로그인 시 "User account is locked" 

개인적으로 특별한 경우가 아니면 굳이 UserDetails를 implements해서 사용할 필요가 없다고 생각합니다

userDetailsService쪽에서 UserDetails를 구현한 User의 생성자가 있기때문에 값만 채워서 리턴하는 방법을 이용하시는걸 추천드립니다.

 

보통의 경우에는 이렇게 구현하지 않겠지만 혹시 삽질하고 계신분들을 위해 남겨둡니다!

회원가입시 데이터가 잘 저장되는데 로그인을 할 때 서버단에서는 에러메시지도 없고 계속해서 postman에서만 403에러 없길래 디버깅을 해봤는데 managerBuilder의 authentication 과정에서 멈추고 있었습니다. 더 깊이 들어가 봤을 때는 isAccountNonLocked() 이 부분이 계속 false처리가 되서 죽길래 검색을 좀 해봤더니 이 메서드가 UserDetails를 오버라이드 한 메서드였고 implements했을 때 기본값이 false로 돼 있기 때문에 true로 고쳐주셔야합니다.

public class Member implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long member_id;

    @Column
    private String id;

    @Column
    private String name;

    @Column
    private String password;

    @Column
    private String email;

    @ElementCollection(fetch = FetchType.EAGER)
    @Builder.Default
    private List<String> roles = new ArrayList<>();

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getUsername() {
        return email;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

OKKY - 스프링 시큐리티 로그인시 "User account is locked"

 

OKKY - 스프링 시큐리티 로그인시 "User account is locked"

이제껏 스프링 부트로 시큐리티 작업하다가 스프링프레임웤으로 하는 중인데 첨 보는 exception이 생겨서 질문드립니다.. CustomUserDetailsService@Service("UserDetailsService") public class CustomUserDetailsService impl

okky.kr