簡體   English   中英

Spring Security OAuth2 - 如何使用 OAuth2Authentication 對象?

[英]Spring Security OAuth2 - How to use OAuth2Authentication object?

我有提供用戶信息的 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();
    }
}

應用程序.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=superadmin@example.org, 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() 方法嗎? 或者也許存在更簡單的解決方案?

好的,經過大量挖掘,我找到了解決方案。

長話短說:應該覆蓋ResourceServerTokenServices.loadAuthentication()方法以從 OAuth2 資源服務器響應中提取自定義主體和/或權限。 主要邏輯封裝在extractAuthentication()方法中。

配置

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

附注

新的Spring Boot版本提供了更靈活的 API。 請參閱PrincipalExtractor接口。 不幸的是,它僅在 2 周前添加,當前穩定的1.3.5.RELEASE版本不支持。

希望這有幫助

使用ResourceServerTokenServicesaccess_token獲取主體

@Autowired
ResourceServerTokenServices  resourceServerTokenServices;

OAuth2Authentication auth = resourceServerTokenServices.loadAuthentication(tokenId);
String principal = auth.getName();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM