当前位置: 首页 > 知识库问答 >
问题:

如何从spring security中oauth服务器返回的用户声明中设置用户权限

归俊
2023-03-14

IsUserInRole总是返回false。@preauthorize(“hasrole('roleName')”)总是引导我到达403。

我可以在哪里放置一些代码来设置当局?

服务器已经通过userinfoendpoint返回了一些用户声明,我的项目收到了它们,我甚至可以在控制器的主要参数中看到它。

@ResponseBody
@RequestMapping("admin")
@PreAuthorize("hasRole('admin')")
public String admin(HttpServletRequest request){
    return "welcome, you are admin!" + request.isUserInRole("ROLE_admin");
}
spring.security.oauth2.client.provider.test.issuer-uri = http://localhost:5000
spring.security.oauth2.client.provider.test.user-name-attribute = name

spring.security.oauth2.client.registration.test.client-id = java
spring.security.oauth2.client.registration.test.client-secret = secret
spring.security.oauth2.client.registration.test.authorization-grant-type = authorization_code
spring.security.oauth2.client.registration.test.scope = openid profile
@ResponseBody
@RequestMapping()
public Object index(Principal user){
    OAuth2AuthenticationToken token = (OAuth2AuthenticationToken)user;
    return token.getPrincipal().getAttributes();
}
{"key":"value","role":"admin","preferred_username":"bob"}

最后,我通过添加以下类得到了这个工作:

@Configuration
public class AppConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.oauth2Login().userInfoEndpoint().userAuthoritiesMapper(this.userAuthoritiesMapper());
        //.oidcUserService(this.oidcUserService());
        super.configure(http);
    }

    private GrantedAuthoritiesMapper userAuthoritiesMapper() {
        return (authorities) -> {
            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

            authorities.forEach(authority -> {
                if (OidcUserAuthority.class.isInstance(authority)) {
                    OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;

                    OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
                    if (userInfo.containsClaim("role")){
                        String roleName = "ROLE_" + userInfo.getClaimAsString("role");
                        mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
                    }
                } else if (OAuth2UserAuthority.class.isInstance(authority)) {
                    OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
                    Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
                    
                    if (userAttributes.containsKey("role")){
                        String roleName = "ROLE_" + (String)userAttributes.get("role");
                        mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
                    }
                }
            });

            return mappedAuthorities;
        };
    }
}

框架变化太快,web上的演示太老了!

共有1个答案

通令
2023-03-14

显然@wjsgzcn answer(编辑1)不起作用,原因如下

>

  • 如果打印OAuth2UserAuthirty类返回的属性,您很快就会注意到JSON数据的内容没有role键,而是有authorities键,因此需要使用该键迭代权限(角色)列表以获得实际的角色名称。

    因此,以下代码行将无法工作,因为OAuth2UserAuthority.getAttributes()返回的JSON数据中没有角色键;

     OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
     Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
     if (userAttributes.containsKey("role")){
         String roleName = "ROLE_" + (String)userAttributes.get("role");
         mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
     }
    

    因此,使用以下方法从getAttributes获取实际角色

    if (userAttributes.containsKey("authorities")){
       ObjectMapper objectMapper = new ObjectMapper();
       ArrayList<Role> authorityList = 
       objectMapper.convertValue(userAttributes.get("authorities"), new 
       TypeReference<ArrayList<Role>>() {});
       log.info("authList: {}", authorityList);
       for(Role role: authorityList){
          String roleName = "ROLE_" + role.getAuthority();
          log.info("role: {}", roleName);
          mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
       }
    }
    

    其中角色是pojo类,如下所示

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Role {
        @JsonProperty
        private String authority;
    }
    

    这样,您将能够获得role_post前缀,这是在向授权服务器成功进行身份验证后授予用户的实际角色,并且向客户机返回授予权限(角色)的列表

    private GrantedAuthoritiesMapper userAuthoritiesMapper() {
        return (authorities) -> {
                Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
    
                authorities.forEach(authority -> {
                    if (OidcUserAuthority.class.isInstance(authority)) {
                        OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;
    
                        OidcIdToken idToken = oidcUserAuthority.getIdToken();
                        OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
                        
                        // Map the claims found in idToken and/or userInfo
                        // to one or more GrantedAuthority's and add it to mappedAuthorities
                        if (userInfo.containsClaim("authorities")){
                            ObjectMapper objectMapper = new ObjectMapper();
                            ArrayList<Role> authorityList = objectMapper.convertValue(userInfo.getClaimAsMap("authorities"), new TypeReference<ArrayList<Role>>() {});
                            log.info("authList: {}", authorityList);
                            for(Role role: authorityList){
                                String roleName = "ROLE_" + role.getAuthority();
                                log.info("role: {}", roleName);
                                mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
                            } 
                        }
    
                    } else if (OAuth2UserAuthority.class.isInstance(authority)) {
                        OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
                        Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
                        log.info("userAttributes: {}", userAttributes);
                        // Map the attributes found in userAttributes
                        // to one or more GrantedAuthority's and add it to mappedAuthorities
                        if (userAttributes.containsKey("authorities")){
                            ObjectMapper objectMapper = new ObjectMapper();
                            ArrayList<Role> authorityList = objectMapper.convertValue(userAttributes.get("authorities"), new TypeReference<ArrayList<Role>>() {});
                            log.info("authList: {}", authorityList);
                            for(Role role: authorityList){
                                String roleName = "ROLE_" + role.getAuthority();
                                log.info("role: {}", roleName);
                                mappedAuthorities.add(new SimpleGrantedAuthority(roleName));
                            } 
                        }
                    }
                });
                log.info("The user authorities: {}", mappedAuthorities);
                return mappedAuthorities;
        };
    }
    
    @Override
        public void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/**").authorizeRequests()
                .antMatchers("/", "/login**").permitAll()
                .antMatchers("/clientPage/**").hasRole("CLIENT")
                .anyRequest().authenticated()
                .and()
                .oauth2Login()
                    .userInfoEndpoint()
                    .userAuthoritiesMapper(userAuthoritiesMapper());
        }
    

  •  类似资料:
    • 扩展程序访问网站和大多数 Chrome API 的能力取决于其声明的权限。 权限应仅限于其功能所需。限制权限可以建立扩展程序的功能,并减少攻击者入侵扩展程序导致的数据入侵的可能。通过显式,最小和可选权限来保护扩展及其用户。 整理权限 权限是固定已知的字符串,它们引用 Chrome API 或 match patterns 以赋予对一个或多个主机的访问权限。它们在 manifest 中列出,并指定为

    • 1)  Excel服务器中设置填报权限 出现填表权限设置界面,设置可以填写该报表的部门与角色,默认是所有部门与角色(系统管理员角色除外)都被选上,(有关权限设置的问题在下面有专门的章节进行论述),如下图: 点击下一步  Excel服务器中设置查看权限 1)E立方 出现查看权限设置界面,设置可以查看该报表的部门与角色,默认是所有部门与角色(系统管理员角色除外)都被选上,(有关权限设置的问题在下面有专

    • 我正试图从现有的应用程序中设计一个具有相当标准的用户管理的微服务:具有认证和授权,并存储用户数据。 我正在开发一个授权服务器来管理用户身份验证和授权,使用作为授权。在另一方面,我必须存储用户的信息/配置文件。 问题:授权服务器应该管理: 授权和用户API?因此,其他微服务可以联系上的授权服务器以获取当前用户,也可以联系以获取完整的用户列表。 还是只有授权,我必须创建用户微服务?因此授权服务器只公开

    • 问题内容: 因此,已经有一个必须在控制台上运行的Python程序设置了。我将使用Javascript为应用程序构建Web GUI界面。我将如何: 一种。开始处理此Python程序的输入/输出,而无需触摸原始代码。 b。通过Javascript调用将控制台输入发送到Python程序。我已经研究了原始的HTTP请求/ AJAX,但不确定如何将其作为输入发送到Python程序。 问题答案: 一种。处理程

    • 问题内容: 我有一个配置有注释的资源服务器,它通过参数引用授权服务器,如下所示: 授权服务器/用户端点返回其扩展名,例如带有电子邮件: 每当访问某些资源服务器端点时,Spring都会通过调用授权服务器的/user端点来验证幕后的访问令牌,并且实际上会获取丰富的用户信息(其中包含例如电子邮件信息,我已经使用Wireshark进行了验证)。 所以问题是,如何在不显式第二次调用授权服务器端点的情况下获取

    • 我已将自己添加到www-data组中,并将web目录的权限递归设置为775。Apache能够读写,但我的用户在尝试通过SFTP添加文件时,会收到“权限被拒绝”的消息。 我做错了什么?我应该有不同的所有权设置吗?