spring-security 如何使我的spring security自定义角色能够识别权限?

yqhsw0fo  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(248)

我正在构建一个springboot应用程序,目前正在尝试实现基于权限的授权。在我的securityConfig文件中,基于角色的授权是有效的,但是基于权限的授权失败了。如下面的SecurityConfig文件所示,在antMatchers的hasAnyRole函数中传递角色是有效的,但是传递权限给hasAnyAuthority是无效的,也就是说,它没有授权。
这是我的SecurityConfig文件

@Override
    protected void configure(HttpSecurity http) throws Exception {
        /*
         * Setting custom login endpoint
         * */
        CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
        customAuthenticationFilter.setFilterProcessesUrl("/api/login");
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.authorizeRequests()
                .antMatchers("/api/login/**", "/api/token/refresh/**").permitAll()
                .antMatchers("/api/users/save/**").permitAll()
                .antMatchers(GET, "/api/users/**").hasAnyAuthority(CAN_ADD_MEMBER_TO_CHAMA.getPermission())
                .antMatchers(GET, "/api/users/**").hasAnyRole(PLATFORM_SUPER_ADMIN.name())
                .anyRequest()
                .authenticated()
                .and();

        http.addFilter(customAuthenticationFilter);
        http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

职务

public enum ApplicationUserRole {
    PLATFORM_SUPER_ADMIN(
            Sets.newHashSet(
                    CAN_CREATE_CHAMA, CAN_DELETE_CHAMA,
                    CAN_UPDATE_CHAMA, CAN_INVITE_NEW_USER)),
    PLATFORM_USER(Sets.newHashSet(CAN_CREATE_CHAMA)),

    CHAMA_MEMBER(Sets.newHashSet(CAN_MAKE_CONTRIBUTION, CAN_INVITE_NEW_USER));

    private final Set<ApplicationUserPermission> permissions;

    ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
        this.permissions = permissions;
    }

    public Set<ApplicationUserPermission> getPermissions() {
        return permissions;
    }

    public Set<SimpleGrantedAuthority> getGrantedAuthorities() {
        Set<SimpleGrantedAuthority> permissions = getPermissions().stream()
                .map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
                .collect(Collectors.toSet());
        permissions.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
        return permissions;
    }
}

使用权限

package com.chama.chamaservice.config;

public enum ApplicationUserPermission {
    CAN_CREATE_CHAMA("CAN_CREATE_CHAMA"),
    CAN_DELETE_CHAMA("CAN_DELETE_CHAMA"),
    CAN_UPDATE_CHAMA("CAN_UPDATE_CHAMA"),

    private final String permission;

    ApplicationUserPermission(String permission) {
        this.permission = permission;
    }

    public String getPermission() {
        return permission;
    }
}

自定义授权筛选器

public class CustomAuthorizationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getServletPath().equals("/api/login") || request.getServletPath().equals("/api/refresh/token")) {
            filterChain.doFilter(request, response);
        } else {
            // Generate new access token from refresh token
            String authorizationHeader = request.getHeader(AUTHORIZATION);
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                try {
                    String token = authorizationHeader.substring("Bearer ".length());
                    Algorithm algorithm = Algorithm.HMAC256("secret".getBytes());
                    JWTVerifier verifier = JWT.require(algorithm).build();
                    DecodedJWT decodedJWT = verifier.verify(token);
                    String phoneNumber = decodedJWT.getSubject();

                    String[] roles = decodedJWT.getClaim("roles").asArray(String.class);
                    Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
                    stream(roles).forEach(role -> {
                        authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); // Populate ROLES
                    });

                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(phoneNumber, null, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    filterChain.doFilter(request, response);
                } catch (Exception e) {
                    log.error("Error logging in: {}", e.getMessage());
                    response.setHeader("error", e.getMessage());
                    response.setStatus(FORBIDDEN.value());
                    Map<String, String> error = new HashMap<>();
                    error.put("message", e.getMessage());
                    response.setContentType(APPLICATION_JSON_VALUE);
                    new ObjectMapper().writeValue(response.getOutputStream(), error);
                }
            } else {
                filterChain.doFilter(request, response);
            }
        }
    }
}
nkhmeac6

nkhmeac61#

在您的自定义过滤器中,您只将 “roles” JWT声明解析为String形式的角色,因此您的SecurityContext对权限(权限)一无所知。
请尝试使用ApplicationUserRole枚举.getGrantedAuthorities()方法来代替此方法,例如:

String[] roles = decodedJWT.getClaim("roles").asArray(String.class);
Collection<SimpleGrantedAuthority> authorities = Arrays.stream(roles)
                .map(ApplicationUserRole::valueOf) // <- parsing every String to ApplicationUserRole
                .map(ApplicationUserRole::getGrantedAuthorities) // <- converting every ApplicationUserRole to a set of GrantedAuthority
                .flatMap(Collection::stream) // <- converting stream of sets to a stream of GrantedAuthority
                .collect(Collectors.toList());
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(phoneNumber, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request, response);

如果 “roles” 声明无法解析为ApplicationUserRole数组,则.valueOf()方法将抛出IllegalArgumentException,并且您的catch块将把它转换为403 http状态响应。

相关问题