spring-boot - 具有多个 IDP 和表单登录的 Spring Security OAuth2:匹配用户
问题描述
我在多个项目中多次使用 Spring Security,包括 Zuul API Gateway 上的 3 条腿 OAuth2 身份验证等。所有工作都非常出色,官方文档非常简洁。
但是有一点我仍然没有从文档中得到。想象一下,您有一个基于 spring 的资源服务器,其中包含多个 ID 提供者,并且您有自己的用户数据库和表单登录。
因此,可以通过表单登录或通过 IDP 之一(比如 Google 或 Facebook)对用户进行身份验证。
问题是:如何将来自任何 IDP 的身份验证与由本地用户增强/映射到本地用户的身份验证对象相匹配?
即:Alice 在您的系统中有一个帐户(在您的数据库中)。她进入她的“个人资料”并声明她也有一个谷歌或 Facebook 帐户。好的,完成,您将此信息保存在系统中的某个位置。
现在,当 Alice 通过社交网络登录到您的系统时,您使用什么 Spring API 来了解通过 Google 输入的 Alice 与已经在您的数据库中注册的 Alice 完全相同?您在哪个 API 中使用基于您的数据库的权限来增强她的身份验证?
提前谢谢各位
解决方案
这通常是通过创建一个包含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();
// ...
}
推荐阅读
- javascript - HTML5 不将 onPaste 识别为事件
- algorithm - 这种场景下如何实现最短路径算法?
- javascript - 非法 base64 字符
- r - 如何计算从列表中采样所有样本的概率?
- reactjs - Reactjs 没有更新 product_number 的新值
- vim - 将复制的内容从 vim 粘贴到 IDE 会插入一个新行
- oracle - ORA-01652: 无法在表空间 TEMP 中将临时段扩展 128
- html - Angular 7.1.4 HTML 避免复制粘贴重组
- sql - Postgresql 从日期数组之间的日期范围中选择
- python-3.x - 缓慢缩放矩形(pygame)