programing

스프링 보안/스프링 부트 - 사용자 역할 설정 방법

firstcheck 2023. 2. 14. 21:59
반응형

스프링 보안/스프링 부트 - 사용자 역할 설정 방법

보안을 사용하여 로그인 했을 때request.isUserInRole()방법.사용자의 역할이 정해지지 않았다고 생각합니다.

보안 설정은 다음과 같습니다.

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled=true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter  {

@Autowired
private DataSource dataSource;

@Autowired
private UserDetailsServiceImplementation userDetailsService;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/signup").permitAll()
            .antMatchers("/").permitAll()
            //.antMatchers("/first").hasAuthority("Service_Center")
            .antMatchers("/login").permitAll()
            .anyRequest().fullyAuthenticated()
    .and().formLogin()
            .loginPage("/login")
            .usernameParameter("email")
            .passwordParameter("password")
            .defaultSuccessUrl("/default")
            .failureUrl("/login?error").permitAll()
    .and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login?logout")
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true).permitAll();
}

@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.userDetailsService(userDetailsService);

}

}

이건 내 거야User엔티티:

 @Entity
 @Table(name="user")
 public class User  implements Serializable{
/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="user_id")
private Long userID;

@Column(name="email_address", nullable = false, unique = true)
private String emailAddress;

@Column(name="password")
private String password;

@Column(name = "role", nullable = false)
@Enumerated(EnumType.STRING)
private Role role;

public User() {
    super();
}

public User(String emailAddress, String password) {
    this.emailAddress = emailAddress;
    this.password = password;
}

public Long getUserID() {
    return userID;
}

public void setUserID(Long userID) {
    this.userID = userID;
}

public String getEmailAddress() {
    return emailAddress;
}

public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public Role getRole() {
    return role;
}

public void setRole(Role role) {
    this.role = role;
}

@Override
public String toString() {
    return "User [userID=" + userID + ", emailAddress=" + emailAddress
            + ", password=" + password + ", role=" + role + "]";
}

public UserDetails toCurrentUserDetails() {
    return CurrentUserDetails.create(this);
}
}

이게 제 목록입니다.Role:

public enum Role {

Fleet_Company, Service_Center, Admin

}

이건 내 거야UserDetailsServiceImplementation:

@Component
public class UserDetailsServiceImplementation implements UserDetailsService    {

@Autowired
private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {
    if ( username == null || username.isEmpty() ){
        throw new UsernameNotFoundException("username is empty");
    }

    User foundUser = userRepository.findByEmailAddress(username);
    if( foundUser != null ){
        System.out.println("FOUND");
        return foundUser.toCurrentUserDetails();

    }
    throw new UsernameNotFoundException( username + "is not found");
}
}

이 클래스가 바로 이 클래스입니다.UserDetails:

public class CurrentUserDetails implements UserDetails {
private Long userID;
private String emailAddress;
private String password;
private Role role;


public CurrentUserDetails(Long userID, String emailAddress, String password, Role role) {
    super();
    this.userID = userID;
    this.emailAddress = emailAddress;
    this.password = password;
    this.role = role;
}


  /*    public static UserDetails create(Users entity) {
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    for(Authorities auth: entity.getAuthorities()){
        authorities.add(new SimpleGrantedAuthority(auth.getId().getAuthority()));
    }
    return new MyUserDetail(entity.getUserId(), entity.getLoginId(), entity.getPassword(), entity.getDisplayName(), authorities);
}*/



public Long getUserID(){
    return this.userID;
}


public Role getRole(){
    return this.role;
}




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


public String getEmailAddress() {
    return this.emailAddress;
}


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

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


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


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

public static UserDetails create(User entity) {
    System.out.println(entity.getUserID()+ entity.getEmailAddress()+ entity.getPassword()+ entity.getRole());
    return new CurrentUserDetails(entity.getUserID(), entity.getEmailAddress(), entity.getPassword(), entity.getRole());
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    // TODO Auto-generated method stub
    return null;
}

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

기본적으로 MySQL 데이터베이스에는 테이블이 1개뿐이고 4개의 열이 있으며 그 중 하나는 '역할'입니다.

근데 아까도 말 그대로request.isUserInRole("Service_Center")FALSE가 반환됩니다.그리고..antMatchers("/first").hasAuthority("Service_Center")그것도 안 돼요.

User Details를 작성할 때 역할의 내용을 직접 입력해야 합니다.

public class SecurityUser implements UserDetails{
    String ROLE_PREFIX = "ROLE_";

    String userName;
    String password;
    String role;

    public SecurityUser(String username, String password, String role){
        this.userName = username;
        this.password = password;
        this.role = role;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();

        list.add(new SimpleGrantedAuthority(ROLE_PREFIX + role));

        return list;
    }

기본적으로는 덮어쓰기 방식을 사용해야 합니다.getAuthorities역할 필드의 내용을 에 입력합니다.GrantedAuthority목록.

Divinto, Zapl, Thorinkor가 말한 것은 옳다.하지만 질문은 롤스가 아니라 "역할"에 관한 것이어야 합니다.또는 사용자와 역할이 한 테이블에 있을 경우 설계가 잘못됩니다.설계 방식을 다시 살펴보는 것이 좋습니다.별도의 역할 엔티티가 있어야 합니다.UserService에서는 다음과 같은 작업을 수행할 수 있습니다.

AppUser user = userRepository.findByUsername(username);

Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); // use list if you wish
for (AppRole role : user.getRoles()) {
    grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(
        user.getUsername(),
        user.getPassword(),
        grantedAuthorities
);

샘플: sample1 sample2 sample3

DB에서 역할 이름을 데이터베이스에 - (예를 들어) ADMIN/EDITOR/VIEWER로 저장하거나 역할을 ROLE_ADMIN/ROLE_...로 역할을 저장할 수 있습니다.그럼 hasRole/has를 사용하세요.권위적이다.도움이 됐으면 좋겠다.

참조용으로 여기를 봐 주세요.

스프링 보안 관련 1

스프링 보안 관련 2

역할을 추가하려면 사용자 이름과 대응하는 역할을 포함하는 테이블이 필요합니다.
사용자에게 ADMIN과 USER의 두 가지 역할이 있다고 가정합니다.

한 명의 사용자가 여러 역할을 가질 수 있습니다.

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    final List<SimpleGrantedAuthority> authorities = new LinkedList<>();
    if (enabled) {
        if (this.getUser().isAdmin()) {
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
    }
        return authorities;
}

이것은, 다음과 같이 말할 수 있습니다.

private UsernamePasswordAuthenticationToken getAuthentication(
final String token, final HttpServletRequest req,
final HttpServletResponse res){
    return new UsernamePasswordAuthenticationToken(userAccount, null,
    userAccount.getAuthorities());
}

이 방법을 사용하여 User.builder 개체를 사용하여 ROLE 또는 Authorities를 로드할 수도 있습니다.이 예에서는 http 요청에서 토큰을 수신하고 있으며 TOKEN 내의 ROLES 목록을 가져옵니다.필요한 역할을 포함하는 간단한 문자열 목록을 UserDetail 구현에 로드할 수 있습니다.

private UserDetails userDetails(final Claims claims) {
    
    UserDetails userDetails = User.builder()
    .username(resolveUserName(claims))
    .password(resolveUserPassword())
    .roles(userRoles(claims))
    .build();
    
    
    return userDetails;
}

여기서 userRoles(claims)는 필요한 모든 역할을 가진 문자열 배열을 반환합니다.

도움이 되었으면 좋겠다

언급URL : https://stackoverflow.com/questions/37615034/spring-security-spring-boot-how-to-set-roles-for-users

반응형