我已经在多个项目上多次使用Spring Security,包括在Zuul API Gateway上进行了3条腿的OAuth2身份验证等。所有工作都很出色,而且官方文档非常简洁明了。
但是有一点我仍然无法从文档中得到。假设您有一个基于弹簧的Resource Server和several ID Providers,并且您拥有自己的用户数据库和表单登录名。
因此,可以通过表单登录或通过IDP之一(例如Google或Facebook)对用户进行身份验证。
问题是:如何将身份验证从您的任何IDP匹配到由本地用户增强/映射到本地用户的身份验证对象?
即:Alice在您的系统中(在数据库中)有一个帐户。她进入自己的“个人资料”,并声明自己也有Google或Facebook帐户。好的,完成了,您可以将此信息保存在系统中的某个位置。
现在,当Alice通过社交网络登录到您的系统时,您使用什么spring API来了解通过Google输入的Alice与已经在数据库中注册的Alice完全相同?您可以使用哪种API通过数据库来增强对她的身份验证?
谢谢,伙计们
答案 0 :(得分:1)
通常这样做的方法是创建一个包含OidcUser
对象和域对象的组合。例如:
@Component
public class MyOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private final OidcUserService delegate = new OidcUserService();
@Override
public OidcUser loadUser(OidcUserRequest oidcUserRequest) {
// the information that comes back from google, et al
OidcUser oidcUser = this.delegate.loadUser(oidcUserRequest);
// the information from your DB
MyUser user = this.myRepository.findUserByXYZ(oidcUser.getXYZ());
return new MyOidcUser(user, oidcUser);
}
private static class MyOidcUser extends MyUser implements OidcUser {
private final OidcUser delegate;
public MyOidcUser(MyUser user, OidcUser oidcUser) {
super(user);
this.delegate = oidcUser;
}
// ... implement delegate methods
}
}
请注意,XYZ
是一些属性,可让您知道Google用户是系统用户。例如,也许这就是电子邮件地址。
这项额外工作的好处是Spring Security会将这个MyOidcUser
对象放入Authentcation#getPrincipal
中。因此,现在,如果需要获取域位,请执行(MyUser) authentication.getPrincipal()
,但是如果需要OIDC位,则请执行(OidcUser) authentication.getPrincipal()
。根据您的用例,您可以执行以下操作:
@GetMapping("/endpoint1")
public String endpoint1(@AuthenticationPrincipal MyUser myUser) {
// ...
}
@GetMapping("/endpoint2")
public String endpoint2(@AuthenticationPrincipal OidcUser oidcUser) {
URL issuer = oidcUser.getIdToken().getIssuer();
// ...
}