最近公司需要将Google关联登录整合到项目的资源服务器中,但是其中遇到了很多坑,在这里记录一下。
环境:
操作系统:win7
jdk版本:1.8
IDEA:2019.2
SpringBoot版本:2.1.6.RELEASE
Spring-cloud-starter-oauth2版本:2.1.0.RELEASE
注意,要做Google关联登录,当然得先才行。
相信在做关于Google关联登录的小伙伴,都应该会使用SpringSecurity+oAuth2来搭建一个本地的认证服务和资源服务,整个认证过程以下图形式展示:
(参考:https://www.funtl.com/zh/spring-security-oauth2/%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81-oAuth2.html)
在微服务架构中,很多服务都可以被看做为资源服务,如:商品服务、用户服务、数据服务等等,这些资源服务都会被oAuth2给保护起来,每次请求这些资源服务都会认证服务器认证授权。
要实现Google关联登录,那么就需要我们这边的服务通过ClientId,Secret以及 /oauth2/auth认证回调地址,以及/oauth2/token获取token的地址,需要注意的一点是我们这边的是“资源服务”,Google那边的是“认证服务”,我们的“资源服务”需要获取到Google用户信息,以及api功能调用,就首先得去Google的认证服务去进行认证鉴权,认证鉴权通过之后,就会获取到用户信息以及access_token信息,拿着Google给的access_token就可以去调Google API的功能接口了。
下面看看我们是如何用我们的资源服务去Google的认证服务去进行认证鉴权,然后获取到用户信息以及token等信息。
设置凭证,在创建凭证的时候,需要将应用类型选择为Web Application:
可以看到,凭证设置好之后,会获取到一个客户端ID以及客户端密钥。而已授权的JavaScript就是我们资源服务的IP+端口号,已货权的重定向URI要设置成:http://server:ip/login 或者是 http://server:ip/login/xxx
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableOAuth2Sso
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/index.html")
.permitAll()
.anyRequest()
.authenticated();
}
}
Insert title here
Click here to Google Login
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
@SpringBootApplication
@RestController
public class OAuth2ResourceApplication {
public static void main(String[] args) {
SpringApplication.run(OAuth2ResourceApplication.class, args);
}
@RequestMapping(value = "user")
public Principal user(Principal principal) {
return principal;
}
}
security:
oauth2:
client:
client-id: 928234317947-34p5hjm9ht9slnohjlu98kerdh6sqrjl.apps.googleusercontent.com
client-secret: hy3uadMLKiZyXqKN0l8IpY8W
access-token-uri: https://www.googleapis.com/oauth2/v3/token
user-authorization-uri: https://accounts.google.com/o/oauth2/auth
token-name: oauth_token
authentication-scheme: query
client-authentication-scheme: form
scope: profile email
registered-redirect-uri: https://www.baidu.com
resource:
user-info-uri: https://www.googleapis.com/userinfo/v2/me
prefer-token-info: false
client-id和client-secret就是刚刚在GoogleAPIS中设置的内容
然而,回调一直循环在http://localhost:9098/login这个url,而又因为这个url没有认证通过,所以即使登录成功,也一直循环卡在登录页面。
找了很久的bug,都没找到原因,当时真是很痛苦,github、google、Stack Overflow各种找解决方案…
知道被同事点拨,发现原来公司VPN只能代理网页请求,然而程序通信“”就无法解决。此时恍然大悟,虽然Google登录成功,但是oAuth2这边回调获取token的时候,一直被墙,所以无法获取到principle,自然无法获取Google登录信息。待安装了一个新的可以将本机IP和DNS代理到国外时,就可以了。
所以针对这种情况,有两种解决方案:
开启VPN,然后再次进行登录授权之后,user信息终于获取到了:
可以看到,principle中包含了google登录用户的详细信息以及tokenValue等信息。