Springboot Security tiene el rol que no funciona

Resuelto arvind.mohan asked hace 7 años • 4 respuestas

No puedo usar hasRoleel método en @PreAuthorizela anotación. También request.isUserInRole(“ADMIN”)da false. ¿Qué me estoy perdiendo? Aunque .hasAuthority(“ADMIN”)funciona bien.

Estoy asignando autoridades a los usuarios desde una base de datos.

arvind.mohan avatar Jan 31 '17 05:01 arvind.mohan
Aceptado

Debe nombrar su autoridad con el prefijo ROLE_a usar isUserInRole; consulte la Referencia de seguridad de Spring :

HttpServletRequest.isUserInRole(String) determinará si SecurityContextHolder.getContext().getAuthentication().getAuthorities()contiene un GrantedAuthoritycon el rol pasado isUserInRole(String). Normalmente, los usuarios no deben pasar el prefijo "ROLE_" a este método, ya que se agrega automáticamente. Por ejemplo, si desea determinar si el usuario actual tiene la autoridad "ROLE_ADMIN", puede utilizar lo siguiente:

boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");

Lo mismo para hasRole(también hasAnyRole), consulte la referencia de seguridad de Spring :

Devuelve truesi el principal actual tiene el rol especificado. De forma predeterminada, si el rol proporcionado no comienza con 'ROLE_', se agregará. Esto se puede personalizar modificando el archivo defaultRolePrefixon DefaultWebSecurityExpressionHandler.

Consulte también Referencia de seguridad de Spring :

46.3.3 ¿Qué significa "ROLE_" y por qué lo necesito en los nombres de mis roles?

Spring Security tiene una arquitectura basada en votantes, lo que significa que una serie de AccessDecisionVoters. Los votantes actúan sobre los "atributos de configuración" que se especifican para un recurso seguro (como la invocación de un método). Con este enfoque, no todos los atributos pueden ser relevantes para todos los votantes y un votante necesita saber cuándo debe ignorar un atributo (abstenerse) y cuándo debe votar para otorgar o denegar el acceso según el valor del atributo. El votante más común es el RoleVoterque por defecto vota siempre que encuentra un atributo con el prefijo "ROLE_". Hace una comparación simple del atributo (como "ROLE_USER") con los nombres de las autoridades que se le han asignado al usuario actual. Si encuentra una coincidencia (tienen una autoridad llamada "ROLE_USER"), vota para conceder el acceso; de lo contrario, vota para denegar el acceso.

dur avatar Jan 30 '2017 23:01 dur

Tuve que improvisar un poco, tal vez haya otras formas más sencillas que la mía, pero en el momento en que trabajé en esto no me quedó más remedio que improvisar un poco, después de una investigación exhaustiva llegué a esta solución. Spring Security tiene una interfaz llamada AccessDecisionManager, deberá implementarla.

@Component
public class RolesAccessDecisionManager implements AccessDecisionManager {
    private final static String AUTHENTICATED = "authenticated";
    private final static String PERMIT_ALL = "permitAll";

    @Override
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        collection.forEach(configAttribute -> {
            if (!this.supports(configAttribute))
                throw new AccessDeniedException("ACCESS DENIED");
        });
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated()) {
            String rolesAsString = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));
            if (configAttribute.toString().contains(rolesAsString))
                return true;
            else
                return (configAttribute.toString().contains(PERMIT_ALL) || configAttribute.toString().contains(AUTHENTICATED));
        }
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

Ahora, para admitir este administrador de decisiones de acceso personalizado con su configuración de seguridad, haga esto en la configuración de seguridad:

@Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
// other configs
    .accessDecisionManager(this.accessDecisionManager)

accessDecisionManageres el bean autowired de la AccessDecisionManagerimplementación que has creado.

Omar Ajmi avatar May 19 '2020 23:05 Omar Ajmi