通过添加spring-boot-starter-oauth2-client
依赖项并在application.properties
中配置OAuth2客户端设置,我在Spring Boot web应用程序中实现了OIDC身份验证。
在Spring Boot和OAuth2指南中;"如何添加本地用户数据库":
如何添加本地用户数据库
许多应用程序需要保存数据关于本地用户的信息,即使将身份验证委派给外部提供者。我们在这里不显示代码,但很容易做到分两步。
为数据库选择后端,并设置一些存储库(比如说,使用Spring Data(为适合您的需要并且可以完全或部分从外部填充身份验证。
实现并公开OAuth2UserService以调用Authorization服务器以及数据库。您的实施可以委托给默认实现,它将完成繁重的调用授权服务器。您的实现应该返回一些东西扩展您的自定义User对象并实现OAuth2User。
提示:在User对象中添加一个字段以链接到中的唯一标识符外部提供者(不是用户名,而是对于外部提供商中的帐户是唯一的(。
我已经搜索了一些,但没有找到摘录中描述的场景的代码示例。
实现上述场景的最佳方式是什么?
我想主要部分是:
- 在OIDC登录时,如果数据库中不存在,则自动创建用户
- web应用程序控制器方法可以访问表示登录用户的数据库对象
更新:
该指南有一个github问题注释,建议查看指南源代码中的custom-error
示例。我想第一部分(在OIDC登录时,如果不存在用户,则自动创建一个用户(可以在调用DefaultOAuth2UserService().loadUser(request)
之后完成。但是第二部分呢?如何使我的自定义数据库支持的用户对象可用于我的web应用程序的控制器方法?
@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService(WebClient rest) {
DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
return request -> {
OAuth2User user = delegate.loadUser(request);
if (!"github".equals(request.getClientRegistration().getRegistrationId())) {
return user;
}
OAuth2AuthorizedClient client = new OAuth2AuthorizedClient
(request.getClientRegistration(), user.getName(), request.getAccessToken());
String url = user.getAttribute("organizations_url");
List<Map<String, Object>> orgs = rest
.get().uri(url)
.attributes(oauth2AuthorizedClient(client))
.retrieve()
.bodyToMono(List.class)
.block();
if (orgs.stream().anyMatch(org -> "spring-projects".equals(org.get("login")))) {
return user;
}
throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "Not in Spring Team", ""));
};
}
Github使用OAuth2UserService<OAuth2UserRequest, OAuth2User>
,您需要的是OAuth2UserService<OidcUserRequest, OidcUser>
。所以你有没有试着创建另一个@Bean
,它插在弹簧期望的正确位置?
如果没有,创建一个像这样的
@Bean
public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
final OidcUserService delegate = new OidcUserService();
return (userRequest) -> {
// Delegate to the default implementation for loading a user
OidcUser user = delegate.loadUser(userRequest);
log.info("User from oauth server: " + user);
//OAuth2AccessToken accessToken = userRequest.getAccessToken();
//Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
//Fetch the authority information from the protected resource using accessToken
//Map the authority information to one or more GrantedAuthority's and add it to mappedAuthorities
//Create a copy of user using mappedAuthorities
//Insert/update local DB
//user = new DefaultOidcUser(mappedAuthorities, user.getIdToken(), user.getUserInfo());
return user;
};
}
我正在为同样的场景而挣扎,但我会添加一些需求:
- DB状态应该用";几乎";每个请求。这是必要的,例如:向用户添加角色应该立即得到反映
到目前为止,我的发现是:
- 自定义OAuth2UserService很好,但它是在会话构建过程中执行的,并不是每次请求都刷新它
- 似乎必须要有一个自定义过滤器来完成此操作
其他人是如何处理的?