SpringSecurityでoauthサーバーから返されるユーザークレームからユーザー権限を設定する方法

wjsgzcn

最近、Spring Security oauth2を使用して、認証サーバーが何らかの理由でIdentityServer4であるSpring Bootプロジェクトを作成しました。プロジェクトに正常にログインしてユーザー名を取得できますが、ユーザーの権限/役割を設定する方法が見つかりません。

request.isUserInRoleは常にfalseを返します。@PreAuthorize( "hasRole( 'rolename')")は常に403につながります。

権限を設定するためのコードはどこに配置できますか?

サーバーはuserinfoエンドポイントを介していくつかのユーザークレームを返しました、そして私のプロジェクトはそれらを受け取りました、そして私はそれを私のコントローラーのプリンシパルパラメーターでさえ見ることができます。

このメソッドは常に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

クレームを印刷します

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

'role'という名前のクレームがあることを示す結果を取得します

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

誰かが私を助けて私に解決策を与えることができますか?

編集1:理由は、oauth2クライアントがエクストラクタを削除したため、userAuthoritiesMapperを実装する必要があります。

最後に、次のクラスを追加してこの作業を行いました。

@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上のデモは古すぎます!

ヨーゼルが見る

私は数時間を費やし、解決策を見つけました。問題はSpringoauthのセキュリティにあり、デフォルトでは、キー「authorities」を使用してトークンからユーザーロールを取得します。そこで、カスタムトークンコンバーターを実装しました。

最初に必要なのはカスタムユーザートークンコンバーターです。クラスは次のとおりです。

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

public class CustomUserTokenConverter implements UserAuthenticationConverter {
    private Collection<? extends GrantedAuthority> defaultAuthorities;
    private UserDetailsService userDetailsService;

    private final String AUTHORITIES = "role";
    private final String USERNAME = "preferred_username";
    private final String USER_IDENTIFIER = "sub";

    public CustomUserTokenConverter() {
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public void setDefaultAuthorities(String[] defaultAuthorities) {
        this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.arrayToCommaDelimitedString(defaultAuthorities));
    }

    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
        Map<String, Object> response = new LinkedHashMap();
        response.put(USERNAME, authentication.getName());
        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
            response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
        }

        return response;
    }

    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey(USER_IDENTIFIER)) {
            Object principal = map.get(USER_IDENTIFIER);
            Collection<? extends GrantedAuthority> authorities = this.getAuthorities(map);
            if (this.userDetailsService != null) {
                UserDetails user = this.userDetailsService.loadUserByUsername((String)map.get(USER_IDENTIFIER));
                authorities = user.getAuthorities();
                principal = user;
            }

            return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
        } else {
            return null;
        }
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        if (!map.containsKey(AUTHORITIES)) {
            return this.defaultAuthorities;
        } else {
            Object authorities = map.get(AUTHORITIES);
            if (authorities instanceof String) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList((String)authorities);
            } else if (authorities instanceof Collection) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection)authorities));
            } else {
                throw new IllegalArgumentException("Authorities must be either a String or a Collection");
            }
        }
    }
}

カスタムトークンコンバーターが必要です。これは次のとおりです。

import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
        OAuth2Authentication authentication = super.extractAuthentication(claims);
        authentication.setDetails(claims);
        return authentication;
    }


}

そして最後に、ResourceServerConfigurationは次のようになります。

import hello.helper.CustomAccessTokenConverter;
import hello.helper.CustomUserTokenConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(final HttpSecurity http) throws Exception {
        // @formatter:off
        http.authorizeRequests()
                .anyRequest().access("hasAnyAuthority('Admin')");
    }
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("arawaks");
    }

    @Bean
    @Primary
    public RemoteTokenServices tokenServices() {
        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setClientId("resourceId");
        tokenServices.setClientSecret("resource.secret");
        tokenServices.setCheckTokenEndpointUrl("http://localhost:5001/connect/introspect");
        tokenServices.setAccessTokenConverter(accessTokenConverter());
        return tokenServices;
    }


    @Bean
    public CustomAccessTokenConverter accessTokenConverter() {
        final CustomAccessTokenConverter converter = new CustomAccessTokenConverter();
        converter.setUserTokenConverter(new CustomUserTokenConverter());
        return converter;
    }

}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Ubuntuサーバーでユーザー権限を設定する方法

分類Dev

Jenkinsで「UpdateCauses」ユーザー権限を設定する方法

分類Dev

サーバーからそれらを使用するためのユーザーのGoogleカレンダーの権限を取得します

分類Dev

ユーザーが設定から権限を取り消すときのAndroidMarshmallowコールバック?

分類Dev

ユーザーの権限を設定する方法

分類Dev

不和でoauthからユーザーIDを取得する方法

分類Dev

OAuth2承認サーバー/ユーザーエンドポイントからカスタムユーザー情報を取得する方法

分類Dev

最小限のユーザー権限を設定する

分類Dev

AmazonRDSでsysadmin権限を持つユーザーを設定する方法

分類Dev

正しい権限を維持しながら、あるユーザーから別のユーザーにディレクトリを移動する

分類Dev

ユーザーの役割と権限を設定するにはどうすればよいですか?

分類Dev

SpringSecurityからJSPの変数にユーザー名をコピーする方法

分類Dev

SpringSecurity-Tomcatレルムからユーザーを読み取る

分類Dev

ユーザーとロールから合計権限を取得するbelongsToMany

分類Dev

AWS コンソールからユーザー権限を変更する

分類Dev

Rubyでユーザーからroot権限を確認するにはどうすればよいですか?

分類Dev

すでに認証されているユーザーをログインページからホームページにリダイレクトする方法

分類Dev

Pytest-django:ユーザー権限を設定する

分類Dev

Pytest-django:ユーザー権限を設定する

分類Dev

目的のユーザーにオーディオ権限を設定する方法

分類Dev

ユーザー入力から列挙型を設定する

分類Dev

ユーザー入力から列挙型を設定する

分類Dev

監視可能であるがクライアントから編集できないユーザー値をサーバーに設定させる

分類Dev

ユーザーにウェブサイトからスクリーンセーバーを離れさせる

分類Dev

GAE:ユーザーをユーザーサービスからoauth2に変換する

分類Dev

ユーザーにaclを設定すると、ls出力のグループ権限が変更されるのはなぜですか?

分類Dev

ユーザーから隠されているAzureADB2Cクレームを送信する

分類Dev

フォームからDjangoでユーザーを作成する

分類Dev

sudoは、スーパーユーザー特権を取得できるユーザーを制限しますか?

Related 関連記事

  1. 1

    Ubuntuサーバーでユーザー権限を設定する方法

  2. 2

    Jenkinsで「UpdateCauses」ユーザー権限を設定する方法

  3. 3

    サーバーからそれらを使用するためのユーザーのGoogleカレンダーの権限を取得します

  4. 4

    ユーザーが設定から権限を取り消すときのAndroidMarshmallowコールバック?

  5. 5

    ユーザーの権限を設定する方法

  6. 6

    不和でoauthからユーザーIDを取得する方法

  7. 7

    OAuth2承認サーバー/ユーザーエンドポイントからカスタムユーザー情報を取得する方法

  8. 8

    最小限のユーザー権限を設定する

  9. 9

    AmazonRDSでsysadmin権限を持つユーザーを設定する方法

  10. 10

    正しい権限を維持しながら、あるユーザーから別のユーザーにディレクトリを移動する

  11. 11

    ユーザーの役割と権限を設定するにはどうすればよいですか?

  12. 12

    SpringSecurityからJSPの変数にユーザー名をコピーする方法

  13. 13

    SpringSecurity-Tomcatレルムからユーザーを読み取る

  14. 14

    ユーザーとロールから合計権限を取得するbelongsToMany

  15. 15

    AWS コンソールからユーザー権限を変更する

  16. 16

    Rubyでユーザーからroot権限を確認するにはどうすればよいですか?

  17. 17

    すでに認証されているユーザーをログインページからホームページにリダイレクトする方法

  18. 18

    Pytest-django:ユーザー権限を設定する

  19. 19

    Pytest-django:ユーザー権限を設定する

  20. 20

    目的のユーザーにオーディオ権限を設定する方法

  21. 21

    ユーザー入力から列挙型を設定する

  22. 22

    ユーザー入力から列挙型を設定する

  23. 23

    監視可能であるがクライアントから編集できないユーザー値をサーバーに設定させる

  24. 24

    ユーザーにウェブサイトからスクリーンセーバーを離れさせる

  25. 25

    GAE:ユーザーをユーザーサービスからoauth2に変換する

  26. 26

    ユーザーにaclを設定すると、ls出力のグループ権限が変更されるのはなぜですか?

  27. 27

    ユーザーから隠されているAzureADB2Cクレームを送信する

  28. 28

    フォームからDjangoでユーザーを作成する

  29. 29

    sudoは、スーパーユーザー特権を取得できるユーザーを制限しますか?

ホットタグ

アーカイブ