整合社交登录-gitee作为第三方授权登录

发布时间 2023-09-13 01:05:33作者: Bingo39

准备

参数名 说明
client_id gitee第三方应用添加成功返回来的标识码
redirect_uri 授权成功后跳转的页面,回调地址
response_type gitee授权的uuid,获得一个code。作用为作为gitee与应用服务间的临时连接标识
Client Secret 密钥,gitee第三方应用添加成功返回来的标识码

备注:
① response_type获取的code后,换取的access_tocken在一定时间内都是不变的,但只能使用一次
② 必须对client_secret,以及access_tocken进行保密【交给后台处理】

Postman调试接口

  1. 在gitee中创建第三方应用
    应用主页: 用户项目的主要页面,一般不直接跳转到主页,还需要回调地址再次发送后获取access_token
    应用主页回调地址: 用户授权后,码云回调到应用,并且回传授权码的地址。【码云会返回一个code值作为标识码,作为后续动作的标识:如获取用户数据,对开放权限操作等】即gulimall项目中http://gulimall.com/oauth2.0/gitee/success 能处理到code值的controller
    权限: 应用对于gitee的权限操作
    gitee授权登录1

  2. 获取code值

redirect_url地址可以是创建应用时候的主页地址也可以是回调地址,主要是后续能处理code值。建议写回调地址

  1. 获取access_token令牌
  1. 获取用户信息

业务代码参考

gitee第三方授权登录流程图:
gulimall社交登录流程图

操作步骤:

  1. 引入http工具类
    (引入引都没影响,为了方便)
  • HttpUtils请从

https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java下载

  1. 创建OAuth2Controller做请求处理
/**
 * 社交登录请求
 */
@Slf4j
@Controller
public class OAuth2Controller {

    @Autowired
    //feign远程调用member服务
    private MemberFeignService memberFeignService;

    @GetMapping("/oauth2.0/gitee/success")
    public String gitee(@RequestParam("code") String code) throws Exception {
        Map<String, String> map = new HashMap();
        map.put("client_id","71fdfac0ffdf265a0c293206db3f2fac2a6c8627bea1ce1ab137d8a28dbb93eb");
        map.put("redirect_uri","http://auth.gulimall.com/oauth2.0/gitee/success");
        map.put("client_secret","77dc9a8ceb8c6e3e624d022236910c2aed370f615bb5188da2d04054c2f42960");
        map.put("code",code);
        map.put("grant_type","authorization_code");
        //1.根据code换取access_token
        HttpResponse response = HttpUtils.doPost("https://gitee.com", "/oauth/token", "post",  new HashMap<>(), map, new HashMap<>());

        //2.处理响应回来的json串
        if(response.getStatusLine().getStatusCode() == 200){
            //获取access_token
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
            //远程调用member服务来处理用户信息注册、校验功能
            R r = memberFeignService.oauth2Login(socialUser);
            if(r.getCode()==0){
                MemberRespVo data = r.getData("data", new TypeReference<MemberRespVo>() {
                });
                log.info("登录成功:用户信息为:{}"+data.toString());
               // 登录成功就跳回首页
                return "redirect:http://gulimall.com";

            }else {
                return "redirect:http://auth.gulimall.com/login.html";
            }

        }else {
            //失败重定向到登录页
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }
}

3.给表usm_member添加字段social_id,access_token,expires_in

备注:正常逻辑,应该对每个授权应用做表单。但该练手项目为了避免麻烦,直接在usm_member表中添加social_id,access_token,expires_in三个字段【默认授权应用之间的用户id都不一样。】


4. 远程调用member服务,做注册/登录用户功能 ```java //MemberController.java /** * 登录功能 * 【社交登录】 */ @PostMapping("/oauth2/login") public R oauth2Login(@RequestBody SocialUser socialUser) throws Exception {
    MemberEntity entity = memberService.login(socialUser);
    if(entity!=null){
        return R.ok().setData(entity);
    }else {
        return R.error(BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getCode(), BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getMsg());
    }
}

```java
//MemberServiceImpl.java
@Override
    public MemberEntity login(SocialUser socialUser) throws Exception {
        //登录和注册合并逻辑
            //备注:视频中“微博”社交不需要Access_token也可以获取用户uid,而gitee则需要再发带token请求
        //2.1 查询当前社交用户的社交账号信息(uid,昵称,性别等)
        Map<String, String> query = new HashMap<>();
        query.put("access_token",socialUser.getAccess_token());
        HttpResponse response = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", new HashMap<String, String>(), query);
        if(response.getStatusLine().getStatusCode() == 200){
            String json = EntityUtils.toString(response.getEntity());
            JSONObject jsonObject = JSON.parseObject(json);
            String uid = jsonObject.get("id").toString();
            //1.判断当前社交用户是否已经登陆过系统
            MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_id", uid));
            if(memberEntity !=null){
                //1.用户有注册记录,更新信息
                MemberEntity updateDate = new MemberEntity();
                updateDate.setId(memberEntity.getId());
                updateDate.setAccessToken(socialUser.getAccess_token());
                updateDate.setExpiresIn(socialUser.getExpires_in());
                //...其他的不重要,更不更新无所谓
                memberDao.updateById(updateDate);

                memberEntity.setAccessToken(socialUser.getAccess_token());
                memberEntity.setExpiresIn(socialUser.getExpires_in());
                return memberEntity;
            }else{
                //2.没有查到当前社交用户记录,就需要注册一个
                MemberEntity register = new MemberEntity();
                try{
                        String name = jsonObject.get("name").toString();
                        String email = jsonObject.get("email").toString();
                        String socialId = jsonObject.get("id").toString();
                    //.....等等信息
                        register.setNickname(name);
                        register.setEmail(email);
                        register.setSocialId(socialId);
                }catch (Exception e){
                    /**
                     * 远程查询昵称这些不重要的,即是出现问题也可以忽略
                     */
                }
                register.setAccessToken(socialUser.getAccess_token());
                register.setExpiresIn(socialUser.getExpires_in());
                memberDao.insert(register);
                return register;
            }
        }else {
            throw new AccessTokenException(response.getStatusLine().getStatusCode(),response.getStatusLine().getReasonPhrase());
        }

    }

5.页面渲染,发送请求

<li>
   <a href="https://gitee.com/oauth/authorize?client_id={gitee提供的client_id}
   &redirect_uri=http://auth.gulimall.com/oauth2.0/gitee/success&response_type=code">
      <img style="height: 18px;width: 18px" src="/static/login/JD_img/gitee-log.png" />
      <span>gitee</span>
   </a>
</li>