web-dev-qa-db-ja.com

Spring Security OAuth2-OAuth2Authenticationオブジェクトの使用方法

ユーザー情報を提供するOAuth2承認サーバーがあります。

_public class User implements Serializable, UserDetails {
    private Long userID;
    private String username;
    private String password;
    private String fullName;
    private String email;
    private String avatar;
    private boolean enabled;
    // etc
}

@RestController
@RequestMapping("/api")
public class APIController {

    @RequestMapping("/me")
    public User me(@AuthenticationPrincipal User activeUser) {
        return activeUser;
    }
}
_

また、OAuth2クライアントを別のSpring Bootアプリケーションとして実装しました。

_@Configuration
@EnableOAuth2Sso
public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.logout()
            .and()
            .antMatcher("/**").authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated();
    }
}
_

application.yml

_security:
  user:
    password: none
  oauth2:
    client:
      clientId:     acme
      clientSecret: acmepassword
      accessTokenUri:       http://localhost:9080/sso/oauth/token
      userAuthorizationUri: http://localhost:9080/sso/oauth/authorize
    resource:
      userInfoUri:    http://localhost:9080/sso/api/me
_

ユーザーは正常に認証されます:

_@Controller
public class MainController {

    @RequestMapping(value = "/")
    public String index(Principal principal) {
        System.out.println(principal);
        // org.springframework.security.oauth2.provider.OAuth2Authentication@c2e723e8: Principal: superadmin; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=<ADDRESS>, sessionId=<SESSION>, tokenType=bearertokenValue=<TOKEN>; Granted Authorities: {userRoleID=1, authority=ROLE_SUPERUSER}
        OAuth2Authentication auth = (OAuth2Authentication) principal;
        System.out.println(auth.getUserAuthentication().getDetails());
        // {userID=1, username=superadmin, password=***, fullName=SuperUser, [email protected], avatar=null, enabled=true ...
        return "index";
    }
}
_

しかし、提供されたOAuth2Authenticationオブジェクトをアプリケーションで使用する方法を理解できません。ほとんど役に立たない。

Thymeleafセキュリティタグを使用しようとしているとき

_<span sec:authentication="principal.fullName">Username</span>
<span sec:authentication="principal.authorities">Authorities</span>
<span sec:authentication="principal.userAuthentication.details.fullName">Usernames</span>
_

..次の例外が発生します。

_Error retrieving value for property "property name here" of authentication object of class org.springframework.security.oauth2.provider.OAuth2Authentication
_

標準のSpring SecurityメソッドisUserInRole()も機能しない:

_System.out.println(servletRequest.isUserInRole("ROLE_SUPERUSER"));
// false
_

カスタムThymeleafセキュリティ方言とhasRole()メソッドを実装する必要がありますか?それとももっと簡単な解決策がありますか?

11
Vespin

わかりました、多くの掘り下げの後、私は解決策を見つけました。

簡単な説明: ResourceServerTokenServices.loadAuthentication() OAuth2リソースサーバーの応答からカスタムプリンシパルやオーソリティを抽出するには、メソッドをオーバーライドする必要があります。 extractAuthentication() メソッドにカプセル化されたメインロジック。

Config

@Configuration
@EnableOAuth2Sso
public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ResourceServerProperties sso;

    @Autowired
    private OAuth2RestOperations restTemplate;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.logout().and().antMatcher("/**").authorizeRequests().antMatchers("/login").permitAll().anyRequest()
                        .authenticated();
    }

    @Bean
    // very important notice: method name should be exactly "userInfoTokenServices"
    public ResourceServerTokenServices userInfoTokenServices() {
        CustomUserInfoTokenServices serv = new CustomUserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId());
        serv.setTokenType(sso.getTokenType());
        serv.setRestTemplate(restTemplate);
        return serv;
    }
}

サービス

public class CustomUserInfoTokenServices implements ResourceServerTokenServices {
    // exactly the same as org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices
    // except extractAuthentication() method
}

[〜#〜] ps [〜#〜]

新しいSpring Bootバージョンは、より柔軟なAPIを提供します。 PrincipalExtractor インターフェースを参照してください。残念ながら2週間前に追加され、現在の安定版1.3.5.RELEASEバージョンではサポートされていません。

お役に立てれば

2
Vespin