使用gitee_使用第三方登录之接入Gitee

作者:陈东东

地址:https://chendd.cn/information/viewInformation/experienceShare/334.a

   在系统管理功能完成后,的这个登录管理功能中我修改了对于第三方登录的实现,目前已经调整了新浪微博、百度和Gitee(新浪与百度的第三方登录目前本站无法继续使用了),本次则是基于Gitee的一些研究分享,提供参考。 

    其实第三方登录的接入也有好多成型的接入方案,但我觉得作为一个开发者还是自行研究实现较为科学,毕竟任何一个实现抛开是否存在价值不说,在整个过程中的问题及解决的过程是一个含有许多滋味的,同时我这个版本的接入上线时也等效于我实现一个统一接入平台,大家可以通过一个地址实现我所有的第三方登录,即:你请求我的接口地址,我给你提供完整的接入实现,乘着余温(刚刚把代码示例全部调通),对Gitee的登录接入列一些非专业的总结:

(1)在Gitee中创建需要接入项目的过程比较简单,修改即时生效,填写应用名称、Logo、回调地址、介绍等信息就可以了,不需要再多的其它资料(开发者认证等等),参考如下图所示:

5c900aa60ce4ba50a0cdc54e3ee3b306.png

(右上角个人头像处-->个人主页-->个人设置-->第三方应用)

(2)它的接口文档(接口示例、具体说明)相比较其它的一些接入来说资源较少,或者说从应用详情或者是其它设置中均为直观的找到API文档相关的介绍地址,经过一番搜索后找到的地址如下:具体接口API文档地址:https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoStargazers?ex=no,OAuth接入地址:https://gitee.com/api/v5/oauth_doc#/,上述地址中有官方提供的较为详细的描述,无代码参考,如果自行编写代码需要拿出你的勇气,迈出你编写的步伐,步骤参考:

524dd1f83578998e2c0834f5bac4cbc2.png

(3)整个接入过程比本站已经实现的其它接入多了一个步骤,它在回调我们项目的时候返回了授权码,我们需要根据授权码再获取Token,最后再根据Token获取具体的对应接口,如本站获取的是用户基本信息,与其它接入参数一致,只获取用户ID、用户昵称、用户头像这三个参数,附上官方提供的接入流程图,参考如下:

47a07b19e799ca139f6e52a873158c81.png

(4)Gitee提供了大量的接口示例,实际上在基本上没有加入任何群,完全个人摸索的情况下,找了许久才找到它的登录接口的,地址为:https://gitee.com/api/v5/oauth_doc#/,参考如下图所示:

c2ade785ff66d539e0ec4535d4c77563.png

参考代码实现

package cn.chendd.third.login.controller;import ...;/** * 第三方登录 - 接入Gitee码云登录 * * @author chendd * @date 2019/12/21 21:55 */@Api(tags = "Gitee账号登录")@ApiSort(40)@RequestMapping(value = "/third-login")@RestController@Slf4jpublic class LoginGiteeController extends ThirdLoginController{    @GetMapping(value = "/gitee" , consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE , produces = MediaType.APPLICATION_JSON_UTF8_VALUE)    @ApiOperation(value = "Gitee登录",notes = CALLBACK_NOTES)    @ApiOperationSupport(order = 10)    public String login(            @ApiParam(value = "朋友站点标识")            @RequestParam(required = false)                    String friend) throws ValidateDataException, WeiboException {        String link = super.getLink(friend);        String clientId = super.getGiteeConfig().get("client_id");        String redirectURI = super.getGiteeConfig().get("redirect_uri");        String authorizeURL = super.getGiteeConfig().get("authorizeURL");        GieteeOauth oauth = new GieteeOauth(authorizeURL , clientId , redirectURI , link);        String authorize = oauth.getAuthorize();        return authorize;    }    @GetMapping(value = "/giteeCallback" , consumes = MediaType.ALL_VALUE , produces = MediaType.APPLICATION_JSON_UTF8_VALUE)    @ApiOperation(value = "Gitee登录回调",notes = "第三方登录 - Gitee登录回调,被动发起请求")    @ApiOperationSupport(order = 20)    public ThirdUserResult giteeCallback(            @ApiParam(value = "gitee回调标识" , required = true) @RequestParam String code ,            @ApiParam("朋友站点标识") @RequestParam(value = "state" , required = false) String redirect) throws Exception {        //获取用户AccessToken        BaseResult baseTokenResult = this.getAccessToken(code);        String tokenResult = baseTokenResult.getResult();        if(! EnumResult.success.name().equals(tokenResult)){            throw new ValidateDataException(baseTokenResult.getMessage());        }        //获取用户        AccessTokenResult tokenResultData = (AccessTokenResult) baseTokenResult.getData();        BaseResult baseTokenUserResult = this.geAccessTokentUserInfo(tokenResultData.getAccessToken());        String tokenUserResult = baseTokenUserResult.getResult();        if(! EnumResult.success.name().equals(tokenUserResult)){            throw new ValidateDataException(baseTokenUserResult.getMessage());        }        AccessTokenUserInfoResult userInfoResult = (AccessTokenUserInfoResult) baseTokenUserResult.getData();        return new ThirdUserResult(String.valueOf(userInfoResult.getId()) , userInfoResult.getName() ,                userInfoResult.getAvatarUrl() , EnumUserSource.Gitee , redirect);    }    /**     * 根据用户授权code获取授权token     */    private BaseResult getAccessToken(String code) throws Exception {        CloseableHttpClient httpClient = HttpClientBuilder.create().build();        List params = new ArrayList<>();        params.add(new BasicNameValuePair("grant_type" , "authorization_code"));        params.add(new BasicNameValuePair("code" , code));        params.add(new BasicNameValuePair("client_id" , super.getGiteeConfig().get("client_id")));        params.add(new BasicNameValuePair("redirect_uri" ,                super.getGiteeConfig().get("redirect_uri")));        params.add(new BasicNameValuePair("client_secret" , super.getGiteeConfig().get("client_secret")));        CloseableHttpResponse response = null;        try {            String url = super.getGiteeConfig().get("authorizeURL") + "/oauth/token";            HttpPost httpPost = new HttpPost(url);            httpPost.setHeader("User-Agent" , "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0");            httpPost.setEntity(new UrlEncodedFormEntity(params));            response = httpClient.execute(httpPost);            String result = EntityUtils.toString(response.getEntity());            return new SuccessResult(JSONObject.parseObject(result , AccessTokenResult.class));        } catch (Exception e) {            return new ErrorResult<>("获取token请求异常,参考:%s" , e.getMessage());        } finally {            CloseUtil.close(response , httpClient);        }    }    /**     * 根据授权token获取对应的用户详细信息     */    private BaseResult geAccessTokentUserInfo(String accessToken) throws Exception {        CloseableHttpClient httpClient = HttpClientBuilder.create().build();        String url = super.getGiteeConfig().get("authorizeURL") + "/api/v5/user?access_token=" + accessToken;        HttpGet httpGet = new HttpGet(url);        httpGet.setHeader("User-Agent" , "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0");        CloseableHttpResponse response = null;        try {            response = httpClient.execute(httpGet);            String result = EntityUtils.toString(response.getEntity());            return new SuccessResult(JSONObject.parseObject(result , AccessTokenUserInfoResult.class));        } catch (Exception e) {            log.error("发送token请求异常:" , e);            return new ErrorResult(String.format("获取token请求异常,参考:%s" , e.getMessage()));        } finally {            CloseUtil.close(response , httpClient);        }    }}package cn.chendd.third.login.custom;import .../** * 接入gitee登录实现 * * @author chendd * @date 2019/12/29 20:59 */@Slf4jpublic class GieteeOauth {    private StringBuilder urlBuilder;    public GieteeOauth(String authorizeURL , String clientId , String redirectURI , String link) {        urlBuilder = new StringBuilder();        try {            urlBuilder.append(authorizeURL)                    .append("/oauth/authorize?client_id=").append(clientId)                    .append("&redirect_uri=").append(URLEncoder.encode(redirectURI , Charsets.UTF_8.name()))                    .append("&response_type=code");            if(StringUtils.isNotBlank(link)){                urlBuilder.append("&state=").append(link);            }        } catch (UnsupportedEncodingException e) {            log.error("构造gitee登录出现错误:" , e);        }    }    public GieteeOauth(String authorizeURL, String code , String clientId ,  String redirectURI , String clientSecret) {        urlBuilder = new StringBuilder();        try {            urlBuilder.append(authorizeURL)                    .append("/oauth/token?grant_type=authorization_code&code=").append(code)                    .append("&client_id=").append(clientId)                    .append("&redirect_uri=").append(URLEncoder.encode(redirectURI , Charsets.UTF_8.name()))                    .append("&client_secret=").append(clientSecret);        } catch (UnsupportedEncodingException e) {            log.error("构造gitee登录出现错误:" , e);        }    }    public String getAuthorize() {        return urlBuilder.toString();    }    public String getToken(){        return urlBuilder.toString();    }}

代码说明

上述代码一定无法通过编译,直接从系统代码里摘出来的,大的方向没问题,只是有细节上的逻辑包装,后面随着博客的开源全部开源,super.getGiteeConfig()是一个从数据库获取配置参数的实现,具体参数参考如下:

48de7009f36d766ce75a668a3f41d040.png

示例演示

(1)请求本站授权

4e8c9c92a9f302ec28f95eacde9fb0fc.png

(2)登录账号并授权

000ee884fdf2eaaf2ddcb7386be7aa0b.png

96d437e8399ea2807a63cfbe98cffec7.png

(3)返回授权后的用户信息

015ed9559d85e484af08d5fc571a9a3e.png

3af967d0a2faac47c27e2f75aaaff6e1.png


版权声明:本文为weixin_32331453原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。