ユーザー情報を提供する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()メソッドを実装する必要がありますか?それとももっと簡単な解決策がありますか?
わかりました、多くの掘り下げの後、私は解決策を見つけました。
簡単な説明: 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バージョンではサポートされていません。
お役に立てれば