web-dev-qa-db-fra.com

Comment définir les autorités utilisateur des demandes d'utilisateur Retour d'un fichier oauth serveur à la sécurité du printemps

J'ai récemment écrit un projet de démarrage de printemps qui utilise Security Spring Oauth2, le serveur Auth ItalyServer4 pour une raison quelconque, je peux vous connecter avec succès et obtenir le nom d'utilisateur dans mon projet, mais je ne trouve aucun moyen de définir l'autorité/le rôle de l'utilisateur.

demande.isuserinrole retourne toujours faux. @Peuthorize ("Hasrole (" Rolename ")") mène toujours à 403.

Où puis-je placer du code pour définir les autorités?

Le serveur a renvoyé certaines créances utilisateur via Userinfo Endpoint et mon projet les a reçus, et je peux même le voir dans le principe param de mon contrôleur.

Cette méthode renvoie toujours 403

@ResponseBody
@RequestMapping("admin")
@PreAuthorize("hasRole('admin')")
public String admin(HttpServletRequest request){
    return "welcome, you are admin!" + request.isUserInRole("ROLE_admin");
}

application.Properties

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

J'imprime les revendications

@ResponseBody
@RequestMapping()
public Object index(Principal user){
    OAuth2AuthenticationToken token = (OAuth2AuthenticationToken)user;
    return token.getPrincipal().getAttributes();
}

et obtenir le défilé des résultats il y a une réclamation nommée "rôle"

{"key":"value","role":"admin","preferred_username":"bob"}

Quelqu'un peut m'aider et me donner une solution s'il vous plaît?

Editer 1 : La raison est que le client OAuth2 a supprimé l'extracteur et je dois mettre en œuvre la machine d'utilisateurMapper.

Enfin, j'ai eu ce travail en ajoutant la classe suivante:

@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;
        };
    }
}

Le cadre change si vite et les démos sur le Web sont trop âgés!

5
wjsgzcn

Apparemment @wjsgzcn réponse (EDIT 1) ne fonctionne pas pour des raisons ci-dessous

  1. Si vous imprimez les attributs renvoyés par le Oauth2UserAuthirty class, vous remarquerez bientôt que le contenu des données JSON ne dispose pas de la clé role a plutôt un authorities Par conséquent, vous devez utiliser cette clé pour itérer la liste des autorités (rôles) pour obtenir le nom de rôle réel.

  2. Par conséquent, les lignes de code suivantes ne fonctionneront pas car il n'y a pas role clé dans les données JSON renvoyées par oauth2UserAuthority.getAttributes();

     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));
     }
    

Ainsi, utilisez plutôt ce qui suit pour obtenir le rôle réel des 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));
   }
}

Où le Role est une classe de pojo comme si

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

De cette façon, vous pourrez obtenir le préfixe ROLE_ Post Post Prefix qui est le rôle réel accordé à l'utilisateur après avoir été authentifié avec succès au serveur d'autorisation et que le client est renvoyé le LIST des autorités accordées ( les rôles).

Maintenant, la complète GrantedAuthoritesMapper ressemble à ce qui suit:

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;
    };
}

Maintenant, vous êtes capable d'utiliser le userAuthorityMapper dans votre oauth2Login comme suit

@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());
    }
0
Jose Mhlanga