Как проверить «hasRole» в коде Java с помощью Spring Security? - PullRequest
110 голосов
/ 11 июня 2010

Как проверить полномочия пользователя или разрешение в Java Code? Например - я хочу показать или скрыть кнопку для пользователя в зависимости от роли. Есть аннотации типа:

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

Как сделать это в коде Java? Что-то вроде:

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

Ответы [ 16 ]

131 голосов
/ 23 июня 2010

вы можете использовать метод isUserInRole объекта HttpServletRequest.

что-то вроде:

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


    if (request.isUserInRole("ROLE_ADMIN")) {
        // code here
    }
}
68 голосов
/ 11 июня 2010

Spring Security 3.0 имеет этот API

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

Вам придется ввести упаковщик, прежде чем использовать его.

SecurityContextHolderAwareRequestWrapper

61 голосов
/ 17 сентября 2012

Вместо того, чтобы использовать цикл для нахождения полномочий от UserDetails, вы можете сделать:

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
45 голосов
/ 19 апреля 2012

Вы можете получить контекст безопасности и затем использовать его:

    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;
    }
14 голосов
/ 05 августа 2010

Вы можете реализовать метод hasRole (), как показано ниже - (Это проверено на Spring Security 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;
  }
10 голосов
/ 05 октября 2011

Я использую это:

@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);
}
6 голосов
/ 07 августа 2017

Вы можете получить некоторую помощь от AuthorityUtils класса. Проверка роли в качестве однострочника:

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

Предупреждение: Это не проверяет иерархию ролей, если таковая существует.

5 голосов
/ 08 октября 2010

Ответ от 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;
}
4 голосов
/ 16 ноября 2017

В большинстве ответов отсутствуют некоторые пункты:

  1. Роль и авторитет не одно и то же в Spring.Смотрите здесь для больше деталей.

  2. Имена ролей равны rolePrefix + authority.

  3. Префикс роли по умолчанию - ROLE_, однако он настраивается.См. здесь .

Следовательно, для правильной проверки роли необходимо соблюдать префикс роли, если он настроен.

К сожалению, настройка префиксов ролей в Spring немного хакерская, во многих местах префикс по умолчанию, ROLE_, жестко закодирован, но в дополнение к этому в Spring проверяется бин типа GrantedAuthorityDefaultsконтекста и, если он существует, его префикс настраиваемой роли соблюдается.

Если собрать всю эту информацию вместе, лучшая реализация средства проверки роли будет выглядеть примерно так:

@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);
    }
}
2 голосов
/ 25 апреля 2019

Эти две аннотации ниже равны, "hasRole" автоматически добавит префикс "ROLE_". Убедитесь, что у вас есть правильная аннотация. Эта роль установлена ​​в UserDetailsService # loadUserByUsername.

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

тогда вы можете получить роль в коде Java.

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){
    System.out.println("user role2");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...