OAuth2简易实战(四)-Github社交联合登录
程序员文章站
2022-04-28 13:56:57
1. OAuth2简易实战(四) Github社交联合登录 1.1. 用到的第三方插件 1.2. 测试步骤 1.2.1. 先在github上注册一个OAuth Apps 我的配置内容如下 1. 需要注意的,这里的最后一个回调地址的配置,格式严格规定,/connect/xxx,最后的github参数对 ......
1. oauth2简易实战(四)-github社交联合登录
1.1. 用到的第三方插件
https://github.com/spring-projects/spring-social-github
1.2. 测试步骤
1.2.1. 先在github上注册一个oauth apps
我的配置内容如下
- 需要注意的,这里的最后一个回调地址的配置,格式严格规定,/connect/xxx,最后的github参数对应了特定页面,后面我通过阅读源码来详细解释
- 注册完之后,会有一个client id和client secret,这是需要配置到程序中的
1.2.2. 属性配置
- applicaton.properties
spring.social.github.app-id=xxxx spring.social.github.app-secret=xxxx
- 属性类
@configurationproperties(prefix = "spring.social.github") public class githubproperties extends socialproperties { }
1.2.3. social核心配置
- 属性配置导入,建立与github连接
@configuration @enablesocial @enableconfigurationproperties(githubproperties.class) public class githubconfiguration extends socialautoconfigureradapter { private final githubproperties properties; public githubconfiguration(githubproperties properties) { this.properties = properties; } @bean @scope(value = "request", proxymode = scopedproxymode.interfaces) public github github(connectionrepository repository) { connection<github> connection = repository .findprimaryconnection(github.class); return connection != null ? connection.getapi() : null; } @bean public connectcontroller connectcontroller( connectionfactorylocator factorylocator, connectionrepository repository) { connectcontroller controller = new connectcontroller( factorylocator, repository); controller.setapplicationurl("http://localhost:8080"); return controller; } @override protected connectionfactory<?> createconnectionfactory() { return new githubconnectionfactory(properties.getappid(), properties.getappsecret()); } }
1.2.4. controller层
@controller public class repositoriescontroller { @autowired private github github; @autowired private connectionrepository connectionrepository; @getmapping public string repositories(model model) { if (connectionrepository.findprimaryconnection(github.class) == null) { return "redirect:/connect/github"; } string name = github.useroperations().getuserprofile().getusername(); string username = github.useroperations().getuserprofile() .getusername(); model.addattribute("name", name); string uri = "https://api.github.com/users/{user}/repos"; githubrepo[] repos = github.restoperations().getforobject(uri, githubrepo[].class, username); model.addattribute("repositories", arrays.aslist(repos)); return "repositories"; } }
- 当我们请求localhost:8080 会重定向到localhost:8080/connect/github ,这又是写在哪呢?查看源代码,会发现在social-web包的connectcontroller类中有
@controller @requestmapping({"/connect"}) public class connectcontroller implements initializingbean {
@requestmapping( value = {"/{providerid}"}, method = {requestmethod.get} ) public string connectionstatus(@pathvariable string providerid, nativewebrequest request, model model) { this.setnocache(request); this.processflash(request, model); list<connection<?>> connections = this.connectionrepository.findconnections(providerid); this.setnocache(request); if (connections.isempty()) { return this.connectview(providerid); } else { model.addattribute("connections", connections); return this.connectedview(providerid); } }
- 进入connectview方法
protected string connectview(string providerid) { return this.getviewpath() + providerid + "connect"; }
- 可以看到,在这里它固定拼接了参数connect,所以,在自己的跳转页面中需要有特定的命名规范,这里一定就是githubconnect.html了
<html> <head> <title>social authcode</title> </head> <body> <h2>connect to github to see your repositories</h2> <form action="/connect/github" method="post"> <input type="hidden" name="scope" value="public_repo user" /> <div class="forminfo"> click the button to share your repositories with <b>social-github</b> </div> <p><button type="submit">connect to github</button></p> </form> </body> </html>
- 显示页面如下
- 点击按钮进行post请求,进入源码如下
@requestmapping( value = {"/{providerid}"}, method = {requestmethod.post} ) public redirectview connect(@pathvariable string providerid, nativewebrequest request) { connectionfactory<?> connectionfactory = this.connectionfactorylocator.getconnectionfactory(providerid); multivaluemap<string, string> parameters = new linkedmultivaluemap(); this.preconnect(connectionfactory, parameters, request); try { return new redirectview(this.connectsupport.buildoauthurl(connectionfactory, request, parameters)); } catch (exception var6) { this.sessionstrategy.setattribute(request, "social_provider_error", var6); return this.connectionstatusredirect(providerid, request); } }
- 层层深入后,会发现它本质还是在组装授权参数,使用的是oauth2的授权码模式,最后组装的http请求为如下,很明显为了去获得授权码
https://github.com/login/oauth/authorize?client_id=9fc0081c3dd4f8b11f86&response_type=code&redirect_uri=http%3a%2f%2flocalhost%3a8080%2fconnect%2fgithub&scope=public_repo+user&state=e37f1891-cd45-47b4-adb4-5c541f777e60&state=48742b99-c04e-4dfd-af0a-f19b0193f1bb&state=c2737022-3cc7-4b80-92ce-fcba2ca9beb4
- 这最后跳转这层的代码如下,封装成buildoauthurl方法进行了组装
public redirectview connect(@pathvariable string providerid, nativewebrequest request) { connectionfactory<?> connectionfactory = this.connectionfactorylocator.getconnectionfactory(providerid); multivaluemap<string, string> parameters = new linkedmultivaluemap(); this.preconnect(connectionfactory, parameters, request); try { return new redirectview(this.connectsupport.buildoauthurl(connectionfactory, request, parameters)); } catch (exception var6) { this.sessionstrategy.setattribute(request, "social_provider_error", var6); return this.connectionstatusredirect(providerid, request); } }
获取授权码后,跳转github登录页面
输入用户名密码正确后立即回调到方法
@requestmapping( value = {"/{providerid}"}, method = {requestmethod.get}, params = {"code"} ) public redirectview oauth2callback(@pathvariable string providerid, nativewebrequest request) { try { oauth2connectionfactory<?> connectionfactory = (oauth2connectionfactory)this.connectionfactorylocator.getconnectionfactory(providerid); connection<?> connection = this.connectsupport.completeconnection(connectionfactory, request); this.addconnection(connection, connectionfactory, request); } catch (exception var5) { this.sessionstrategy.setattribute(request, "social_provider_error", var5); logger.warn("exception while handling oauth2 callback (" + var5.getmessage() + "). redirecting to " + providerid + " connection status page."); } return this.connectionstatusredirect(providerid, request); }
- 通过授权码再去取得token
- 再继续跳转/connect/github
@requestmapping( value = {"/{providerid}"}, method = {requestmethod.get} ) public string connectionstatus(@pathvariable string providerid, nativewebrequest request, model model) { this.setnocache(request); this.processflash(request, model); list<connection<?>> connections = this.connectionrepository.findconnections(providerid); this.setnocache(request); if (connections.isempty()) { return this.connectview(providerid); } else { model.addattribute("connections", connections); return this.connectedview(providerid); } }
- 此时connections有值,进入connectedview方法
protected string connectedview(string providerid) { return this.getviewpath() + providerid + "connected"; }
- 由此可以知道,下个页面我们命名也定下来了,githubconnected.html,这里简单一个点击连接,跳转到主页
<html> <head> <title>social authcode</title> </head> <body> <h2>connected to github</h2> <p> click <a href="/">here</a> to see your repositories. </p> </body> </html>
- 到此其实授权操作都已经完成了,接下来就是正式调用github需要权限的接口了,点击here
代码学习地址 https://github.com/spring2go/oauth2lab
上一篇: 哈哈,被吓到了!