欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

OAuth2简易实战(四)-Github社交联合登录
我的配置内容如下
OAuth2简易实战(四)-Github社交联合登录

  1. 需要注意的,这里的最后一个回调地址的配置,格式严格规定,/connect/xxx,最后的github参数对应了特定页面,后面我通过阅读源码来详细解释
  2. 注册完之后,会有一个client id和client secret,这是需要配置到程序中的
    OAuth2简易实战(四)-Github社交联合登录

1.2.2. 属性配置

  1. applicaton.properties
spring.social.github.app-id=xxxx
spring.social.github.app-secret=xxxx
  1. 属性类
@configurationproperties(prefix = "spring.social.github")
public class githubproperties extends socialproperties {

}

1.2.3. social核心配置

  1. 属性配置导入,建立与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";
    }

}
  1. 当我们请求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);
        }
    }
  1. 进入connectview方法
    protected string connectview(string providerid) {
        return this.getviewpath() + providerid + "connect";
    }
  1. 可以看到,在这里它固定拼接了参数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>
  1. 显示页面如下

OAuth2简易实战(四)-Github社交联合登录

  1. 点击按钮进行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);
        }
    }
  1. 层层深入后,会发现它本质还是在组装授权参数,使用的是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
  1. 这最后跳转这层的代码如下,封装成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);
        }
    }
  1. 获取授权码后,跳转github登录页面
    OAuth2简易实战(四)-Github社交联合登录
    OAuth2简易实战(四)-Github社交联合登录
    OAuth2简易实战(四)-Github社交联合登录

  2. 输入用户名密码正确后立即回调到方法

    @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);
    }
  1. 通过授权码再去取得token

OAuth2简易实战(四)-Github社交联合登录

  1. 再继续跳转/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);
        }
    }
  1. 此时connections有值,进入connectedview方法
    protected string connectedview(string providerid) {
        return this.getviewpath() + providerid + "connected";
    }
  1. 由此可以知道,下个页面我们命名也定下来了,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>

OAuth2简易实战(四)-Github社交联合登录

  1. 到此其实授权操作都已经完成了,接下来就是正式调用github需要权限的接口了,点击here

OAuth2简易实战(四)-Github社交联合登录

代码学习地址 https://github.com/spring2go/oauth2lab