如何将 OAuth 身份验证与 Spring Security 联系起来
Posted
技术标签:
【中文标题】如何将 OAuth 身份验证与 Spring Security 联系起来【英文标题】:How to tie OAuth authentication with Spring Security 【发布时间】:2017-08-02 18:46:22 【问题描述】:我有一个 Grails 2.5.3 应用程序,目前使用 spring 安全插件进行身份验证。用户使用用户名/密码登录。
我现在更新了应用程序以支持 OAuth 身份验证(使用 ScribeJava)。用户可以单击将他们重定向到 OAuth 提供者页面的链接,并在成功输入凭据后将他们重定向回我的应用程序。但是,我无法将此功能与 spring 安全插件绑定,因此当用户被重定向回我的应用程序时(从 OAuth 成功登录后),我实际上可以看到他们已登录并继续使用我所有的 spring像<sec:ifLoggedIn>
这样的安全好东西。
有谁知道这样做的方法或有一个我可以看看的例子吗?
这是我使用 OAuth 对用户进行身份验证的方式:
//called when user clicks "login using oauth"
def authenticate()
OAuthService service = new ServiceBuilder()
.apiKey(grailsApplication.config.my.sso.clientid)
.apiSecret(grailsApplication.config.my.sso.clientsecret)
.build(MyApi.instance());
String url = service.getAuthorizationUrl();
return redirect(url: url)
//called when oauth provider redirects to my application
def authorization_code()
def code = params.code
OAuthService service = new ServiceBuilder()
.apiKey(grailsApplication.config.my.sso.clientid)
.apiSecret(grailsApplication.config.my.sso.clientsecret)
.build(MyApi.instance());
println code
OAuth2AccessToken accessToken = service.getAccessToken(code);
String userProfileUrl = grailsApplication.config.my.sso.authdomain+"/userinfo"
final OAuthRequest request = new OAuthRequest(Verb.GET, userProfileUrl);
service.signRequest(accessToken, request);
final Response response = service.execute(request);
println(response.getCode());
println(response.getBody());
render (text: code)
【问题讨论】:
以下答案对您有帮助吗? 【参考方案1】:每当您通过OAuth
进行身份验证时,远程服务器每次都会返回一个unique id (some numeric value)
。
您可以使用该id
来验证您的最终用户,并使用springsecurity.reauthenticate()
方法对用户进行身份验证。
步骤:
-
当用户与服务提供商连接(首次验证)时。
服务提供商向您发送
unique id
。将 unique id
保存在
用户表。
当用户通过该服务提供商登录时。再次服务提供商
发送unique id
。检查您的系统中是否存在unique id
,
如果用户存在该唯一ID,则使用
springsecurity.reauthenticate(userInstance)
方法来验证用户。现在您可以使用弹簧安全功能。
查看链接:http://www.jellyfishtechnologies.com/grails-2-2-0-integration-with-facebook-using-grails-oauth-plugin/
【讨论】:
【参考方案2】:假设您从 Oauth 提供商那里获得了用户详细信息,您只需要 设置特定用户的安全上下文
通过解析JSON之类的方式获取用户详细信息
def oauthResponse = JSON.parse(response?.getBody())
Map data = [
id : oauthResponse.id,
email : oauthResponse.email,
name : oauthResponse.name,
first_name : oauthResponse.given_name,
last_name : oauthResponse.family_name,
gender : oauthResponse.gender,
link : oauthResponse.link
]
在我们的例子中,我们使用电子邮件 ID 作为用户名。
因此,当我们获取用户数据时,只需检查用户是否已在系统中注册或如下所示
//load the user details service bean
def userDetailsService
//check if user is already registered on our system
User user = User.findByEmail(data?.email)
if (user)
//If user exists load his context
userDetails = userDetailsService.loadUserByUsername(data?.email)
else
//create the new user
//Assign the role to it
//load his context as below
userDetails = userDetailsService.loadUserByUsername(data?.email)
用户注册成功后,我们只需要像下面这样加载他的上下文
def password
//setting spring security context
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, password == null ? userDetails.getPassword() : password, userDetails.getAuthorities()))
一旦加载了 spring 安全上下文,您就可以将用户重定向到您的登录页面。
现在 oauth 用户将像任何其他具有相同角色的用户一样访问资源。
【讨论】:
以上是关于如何将 OAuth 身份验证与 Spring Security 联系起来的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Boot OAuth2 针对 Google 进行身份验证时如何将 google 用户电子邮件发送到白名单用户
在 Spring Boot 2 上实现基于过滤器的 JWT 身份验证与 OAuth2 JWT 身份验证
如何在 spring-security-oauth 中获取经过身份验证的用户
如何在 Spring Boot oauth2 资源服务器中使用自定义身份验证标头