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!
Apparemment @wjsgzcn réponse (EDIT 1)
ne fonctionne pas pour des raisons ci-dessous
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.
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());
}