sourcecode

Spring Security를 사용하여 Java 코드에서 "hasRole"을 확인하는 방법

copyscript 2023. 1. 10. 21:15
반응형

Spring Security를 사용하여 Java 코드에서 "hasRole"을 확인하는 방법

Java Code에서 사용자 권한 또는 권한을 확인하는 방법? 예를 들어 역할에 따라 사용자에 대한 버튼을 표시하거나 숨깁니다.다음과 같은 주석이 있습니다.

@PreAuthorize("hasRole('ROLE_USER')")

자바 코드로 만드는 방법?예를 들어 다음과 같습니다.

if(somethingHere.hasRole("ROLE_MANAGER")) {
   layout.addComponent(new Button("Edit users"));
}

HttpServletRequest 객체의 isUserInRole 메서드를 사용할 수 있습니다.

예를 들어 다음과 같습니다.

public String createForm(HttpSession session, HttpServletRequest request,  ModelMap   modelMap) {


    if (request.isUserInRole("ROLE_ADMIN")) {
        // code here
    }
}

Spring Security 3.0에는 이 API가 있습니다.

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

사용하기 전에 포장지를 주사해야 합니다.

Security Context Holder Aware Request Wrapper

루프를 사용하여 UserDetails에서 권한을 찾는 대신 다음을 수행할 수 있습니다.

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));

보안 콘텍스트를 취득한 후, 다음과 같이 사용할 수 있습니다.

    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.context.SecurityContext;
    import org.springframework.security.core.context.SecurityContextHolder;

    protected boolean hasRole(String role) {
        // get security context from thread local
        SecurityContext context = SecurityContextHolder.getContext();
        if (context == null)
            return false;

        Authentication authentication = context.getAuthentication();
        if (authentication == null)
            return false;

        for (GrantedAuthority auth : authentication.getAuthorities()) {
            if (role.equals(auth.getAuthority()))
                return true;
        }

        return false;
    }

다음과 같이 hasRole() 메서드를 구현할 수 있습니다(이것은 다른 버전에 대해서는 확실하지 않은 봄 보안 3.0.x에서 테스트됩니다).

  protected final boolean hasRole(String role) {
    boolean hasRole = false;
    UserDetails userDetails = getUserDetails();
    if (userDetails != null) {
      Collection<GrantedAuthority> authorities = userDetails.getAuthorities();
      if (isRolePresent(authorities, role)) {
        hasRole = true;
      }
    } 
    return hasRole;
  }
  /**
   * Get info about currently logged in user
   * @return UserDetails if found in the context, null otherwise
   */
  protected UserDetails getUserDetails() {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserDetails userDetails = null;
    if (principal instanceof UserDetails) {
      userDetails = (UserDetails) principal;
    }
    return userDetails;
  }
  /**
   * Check if a role is present in the authorities of current user
   * @param authorities all authorities assigned to current user
   * @param role required authority
   * @return true if role is present in list of authorities assigned to current user, false otherwise
   */
  private boolean isRolePresent(Collection<GrantedAuthority> authorities, String role) {
    boolean isRolePresent = false;
    for (GrantedAuthority grantedAuthority : authorities) {
      isRolePresent = grantedAuthority.getAuthority().equals(role);
      if (isRolePresent) break;
    }
    return isRolePresent;
  }

이것을 사용하고 있습니다.

@RequestMapping(method = RequestMethod.GET)
public void welcome(SecurityContextHolderAwareRequestWrapper request) {
    boolean b = request.isUserInRole("ROLE_ADMIN");
    System.out.println("ROLE_ADMIN=" + b);

    boolean c = request.isUserInRole("ROLE_USER");
    System.out.println("ROLE_USER=" + c);
}

AuthorityUtils 클래스에서 도움을 받을 수 있습니다.원라이너로서의 역할 확인:

if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) {
    /* ... */
}

주의: 역할 계층이 존재하는 경우 이 작업은 확인하지 않습니다.

대부분의 답변에는 몇 가지 요점이 누락되어 있습니다.

  1. 봄에는 역할과 권위가 같지 않다.자세한 내용은 여기를 참조하십시오.

  2. 은 음음음 role role are are role role role role role role role role 。rolePrefix+authority.

  3. 는 "Default Role Prefix" 입니다.ROLE_단, 설정 가능합니다.여기 보세요.

따라서 역할 프레픽스가 설정되어 있는 경우 적절한 역할체크를 실시할 필요가 있습니다.

기본 프레픽스인 "Default Prefix"는 "Default prefix는 "Default prefix"입니다.ROLE_되어 그 에 타입의 빈, 타입의 빈, 타입의 빈, 타입의 빈, 타입의 있습니다.GrantedAuthorityDefaults는 Spring 컨텍스트에서 체크되며, 이 컨텍스트가 존재하는 경우 해당 컨텍스트에 있는 커스텀롤 프리픽스가 존중됩니다.

이러한 모든 정보를 종합하면 다음과 같은 롤 체커의 구현이 효율화됩니다.

@Component
public class RoleChecker {

    @Autowired(required = false)
    private GrantedAuthorityDefaults grantedAuthorityDefaults;

    public boolean hasRole(String role) {
        String rolePrefix = grantedAuthorityDefaults != null ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
        return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
                .map(Authentication::getAuthorities)
                .map(Collection::stream)
                .orElse(Stream.empty())
                .map(GrantedAuthority::getAuthority)
                .map(authority -> rolePrefix + authority)
                .anyMatch(role::equals);
    }
}

JoseK로부터의 응답은 HTTP 요구에 대한 참조에서 웹 레이어와의 결합을 도입하지 않는 서비스 레이어에서는 사용할 수 없습니다.서비스 계층에서 역할을 해결하려면 Gopi의 답변을 참고하십시오.

하지만 바람이 좀 깁니다.인증에서 바로 권한에 액세스할 수 있습니다.따라서 사용자가 로그인하고 있다고 가정할 수 있는 경우는 다음과 같습니다.

/**
 * @return true if the user has one of the specified roles.
 */
protected boolean hasRole(String[] roles) {
    boolean result = false;
    for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
        String userRole = authority.getAuthority();
        for (String role : roles) {
            if (role.equals(userRole)) {
                result = true;
                break;
            }
        }

        if (result) {
            break;
        }
    }

    return result;
}

아래 두 개의 주석은 동일합니다. "hasRole"은 접두사 "ROLE_"을 자동으로 추가합니다.올바른 주석이 있는지 확인하십시오.이 역할은 UserDetailsService#loadUserByUsername으로 설정됩니다.

@PreAuthorize("hasAuthority('ROLE_user')")
@PreAuthorize("hasRole('user')")

그러면 자바 코드에서 역할을 얻을 수 있습니다.

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){
    System.out.println("user role2");
}

이것은 반대쪽에서 온 질문이지만, 이것을 알아내기 위해 인터넷을 검색해야 했기 때문에 나는 그것을 던져버리고 싶었다.

역할을 확인하는 방법은 많지만 실제로 확인하는 내용은 has Role('blah')이라고 할 때 많이 말하지 않습니다.

HasRole은 현재 인증된 주체에 대해 부여된 권한을 확인합니다.

has Role ("blah")는 has Authority ("blah")의미합니다.

적이 있는 는, 「이 작업을 이 클래스는 get 「Implements User Details」라고 불리는 합니다.에는 기본적으로 가지 해요.new SimpleGrantedAuthority("some name")어떤 논리에 근거한 목록으로 이동합니다.에는 has Role이 있습니다.

이 컨텍스트에서 UserDetails 객체는 현재 인증된 주체입니다.인증 프로바이더, 특히 이를 실현하는 인증 매니저에서는 몇 가지 마법이 발생합니다.

이상하게도 스프링 보안 접근컨트롤은 자바 베이스가 아닌 표현 베이스이기 때문에 이 문제에 대한 표준적인 해결책은 없다고 생각합니다.소스 코드에서 DefaultMethodSecurity를 확인할 수 있습니다.Expression Handler에서 그들이 하고 있는 것을 재사용할 수 있는지 확인합니다.

이 프로젝트에서는 역할 계층을 사용하고 있지만, 위의 답변의 대부분은 특정 역할만 확인하는 것을 목적으로 하고 있습니다.즉, 주어진 역할만 확인하는 것일 뿐 해당 역할과 계층 위는 확인하지 않습니다.

이를 위한 솔루션:

@Component
public class SpringRoleEvaluator {

@Resource(name="roleHierarchy")
private RoleHierarchy roleHierarchy;

public boolean hasRole(String role) {
    UserDetails dt = AuthenticationUtils.getSessionUserDetails();

    for (GrantedAuthority auth: roleHierarchy.getReachableGrantedAuthorities(dt.getAuthorities())) {
        if (auth.toString().equals("ROLE_"+role)) {
            return true;
        }
    }
    return false;
}

Role Hierarchy는 spring-security.xml의 빈으로 정의되어 있습니다.

늦더라도 안하는 것보다는 낫지, 내 2센트어치를 넣을게.

JSF 월드에서 관리 대상 빈에서 다음을 수행했습니다.


HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, "");

위에서 설명한 바와 같이, 다음과 같이 긴 시간 동안 할 수 있는 것으로 알고 있습니다.


Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
    userDetails = (UserDetails) principal;
    Collection  authorities = userDetails.getAuthorities();
}

@gouki가 제일 좋아!

봄이 진짜 어떻게 하는지 보여주는 단서일 뿐이야.

라는 이름의 클래스가 있다.SecurityContextHolderAwareRequestWrapper'하다'를 시행하고 있습니다.ServletRequestWrapper

SecurityContextHolderAwareRequestWrapper 무시하다isUserInRole 검색 " " " "Authentication(스프링에 의해 관리됨)을 사용하여 사용자에게 역할이 있는지 여부를 확인합니다.

SecurityContextHolderAwareRequestWrapper을 사용하다

    @Override
    public boolean isUserInRole(String role) {
        return isGranted(role);
    }

 private boolean isGranted(String role) {
        Authentication auth = getAuthentication();

        if( rolePrefix != null ) {
            role = rolePrefix + role;
        }

        if ((auth == null) || (auth.getPrincipal() == null)) {
            return false;
        }

        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();

        if (authorities == null) {
            return false;
        }

        //This is the loop which do actual search
        for (GrantedAuthority grantedAuthority : authorities) {
            if (role.equals(grantedAuthority.getAuthority())) {
                return true;
            }
        }

        return false;
    }

사용자 역할은 다음 방법으로 확인할 수 있습니다.

  1. SecurityContextHolder에서 콜 스태틱 메서드를 사용하는 경우:

    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_NAME"))) { //do something}

  2. Http Servlet Request 사용

@GetMapping("/users")
public String getUsers(HttpServletRequest request) {
    if (request.isUserInRole("ROLE_NAME")) {
      
    }

사용자 모델에 다음과 같은 'hasRole' 메서드를 추가합니다.

public boolean hasRole(String auth) {
    for (Role role : roles) {
        if (role.getName().equals(auth)) { return true; }
    }
    return false;
}

보통 인증된 사용자가 관리자 역할을 가지고 있는지 확인하기 위해 사용합니다.

Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // This gets the authentication
User authUser = (User) authentication.getPrincipal(); // This gets the logged in user
authUser.hasRole("ROLE_ADMIN") // This returns true or false

Java8을 사용한 My 어프로치, 혼수상태의 역할 분리를 통해 참 또는 거짓을 알 수 있습니다.

    public static Boolean hasAnyPermission(String permissions){
    Boolean result = false;
    if(permissions != null && !permissions.isEmpty()){
        String[] rolesArray = permissions.split(",");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        for (String role : rolesArray) {
            boolean hasUserRole = authentication.getAuthorities().stream().anyMatch(r -> r.getAuthority().equals(role));
            if (hasUserRole) {
                result = true;
                break;
            }
        }
    }
    return result;
}

주석을 사용할 수 있습니다.@Secured또는@RolesAllowed또는@PreAuthorise/@PostAuthorise스프링 보안에서요

주의:이 코드를 추가해야 합니다.

@Configuration
@EnableGlobalMethodSecurity(
    securedEnabled = true, 
    jsr250Enabled = true, 
    prePostEnabled = true
)
public class MyConfig extends WebSecurityConfigurerAdapter{
}

configure 클래스 앞에 있습니다.3개의 파라미터를 모두 사용할 필요는 없습니다.securedEnabled,jsr250Enabled,prePostEnabled. 사용하려는 주석에 따라 하나만 필요합니다.

그런 다음 컨트롤러 클래스에 역할 확인 주석을 추가합니다.

@Secured("ROLE_admin")
@GetMapping("/hello")
public String hello(){
    return "hello";
}

또는

@RolesAllowed("ROLE_admin")
@GetMapping("/hello")
public String hello(){
    return "hello";
}

또는

@PreAuthorize("hasRole('ROLE_user')")
@GetMapping("/hello")
public String hello(){
    return "hello";
}

여기 튜토리얼이 있습니다.https://www.baeldung.com/spring-security-method-security

언급URL : https://stackoverflow.com/questions/3021200/how-to-check-hasrole-in-java-code-with-spring-security

반응형