Spring

 - Spring security Role 관련 이모저모

저번 주 내내 고생한 프로젝트에서 인증 파트를 맡았는데 스프링도 잘 모르는 상태로 security 를 다루려고 하니 어려움이 많았는데 가장 시간을 많이 할애했던 Role에 대해 이야기 해보려 한다.

 

Role의 쓰임새는 사용자의 Role에 따라 특정 url에 대한 접근을 제어하기 위함이다.

가장 많이 쓰이는 메소드는 requestMatchers.~~~이다.

//Role에 관계없이 모든 사용자가 이용가능
.requestMatchers("/api/user/**").permitAll()

//Role이 USER인 사용자만 이용가능. 근데 여기서는 "ROLE"을 앞에 알아서 붙여주기 때문에 "ROLE_USER"하면 오류
.requestMatchers({uri}).hasRole("USER")

//hasRole과 동일한 기능
.requestMatchers({uri)).hasAuthority("ROLE_USER")

 

hasAnyRole 로 해서 여러 권한도 넣어줄 수 있고 한데 주의할 건 Role이 들어간 메소드는 ROLE_을 앞에 붙여준다는 의미이다. 오류 메시지에도 잘 나오니까 크게 걱정할 필요는 없다.

 

그럼 과연 이 ROLE들을 어떻게 구분하는 것일까. 비밀은 바로 UserDetails에 있다.

 

UserDetails는 security에서 제공하는 인터페이스로 사용자에 대한 인증에 이용된다.

public interface UserDetails extends Serializable {

    /**
     * Returns the authorities granted to the user. Cannot return <code>null</code>.
     * @return the authorities, sorted by natural key (never <code>null</code>)
     */
    Collection<? extends GrantedAuthority> getAuthorities();

    /**
     * Returns the password used to authenticate the user.
     * @return the password
     */
    String getPassword();

    /**
     * Returns the username used to authenticate the user. Cannot return
     * <code>null</code>.
     * @return the username (never <code>null</code>)
     */
    String getUsername();

    /**
     * Indicates whether the user's account has expired. An expired account cannot be
     * authenticated.
     * @return <code>true</code> if the user's account is valid (ie non-expired),
     * <code>false</code> if no longer valid (ie expired)
     */
    boolean isAccountNonExpired();

    /**
     * Indicates whether the user is locked or unlocked. A locked user cannot be
     * authenticated.
     * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
     */
    boolean isAccountNonLocked();

    /**
     * Indicates whether the user's credentials (password) has expired. Expired
     * credentials prevent authentication.
     * @return <code>true</code> if the user's credentials are valid (ie non-expired),
     * <code>false</code> if no longer valid (ie expired)
     */
    boolean isCredentialsNonExpired();

    /**
     * Indicates whether the user is enabled or disabled. A disabled user cannot be
     * authenticated.
     * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
     */
    boolean isEnabled();

}

 

함수 명들만 보더라도 사용자 인증에 가져다 쓰라고 만든 것 같다.

UserDetails에서 Role과 관련된 메소드는 getAuthorities()이다.  본인이 커스텀하기 나름이겠지만 이 함수 리턴값에 특정 유저에 대한 모든 권한 리스트를 담아주면  된다.

 

이번에 가장 헷갈렸던 부분!

hasRole("USER")가 호출 -> securitycontextholder에서 UserDetails 가져옴 -> UserDetails.getAuthorities() 에 "ROLE_USER" 가 존재하는지 확인 -> 요청을 막거나 허가.

 

컨트롤러 단에서 권한을 검증하는 @Secured @PreAuthorize도 있다.

간혹 jwt claim에 권한을 넣어주는 경우도 있는데 이는 클라이언트에게 유저의 권한을 활용할 수 있도록 하거나

jwt를 완전히 신용한다면 따로 UserDetails를 검사하지 않고 넘겨주는 필터를 적용할 수도 있겠다.

알고리즘

- 프로그래머스 : 압축(Level 2, 해시, 문자열)

느낀 점

.

 

'TIL' 카테고리의 다른 글

[23.11.30]  (1) 2023.12.01
[23.11.29]  (0) 2023.11.29
[23.11.22]  (1) 2023.11.22
[23.11.21]  (0) 2023.11.21
[23.11.20]  (0) 2023.11.20

+ Recent posts