整合社交登录-gitee作为第三方授权登录
<h2 id="准备">准备</h2><ul>
<li>gitee oauth2文档<br>
gitee open API文档</li>
<li>测试接口工具:postman</li>
<li>参数对照表</li>
</ul>
<table>
<thead>
<tr>
<th>参数名</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>client_id</td>
<td>gitee第三方应用添加成功返回来的标识码</td>
</tr>
<tr>
<td>redirect_uri</td>
<td>授权成功后跳转的页面,回调地址</td>
</tr>
<tr>
<td>response_type</td>
<td>gitee授权的uuid,获得一个<code>code</code>。作用为作为gitee与应用服务间的临时连接标识</td>
</tr>
<tr>
<td>Client Secret</td>
<td>密钥,gitee第三方应用添加成功返回来的标识码</td>
</tr>
</tbody>
</table>
<blockquote>
<p>备注:<br>
① response_type获取的code后,换取的access_tocken在一定时间内都是不变的,但只能使用一次<br>
② 必须对client_secret,以及access_tocken进行保密【交给后台处理】</p>
</blockquote>
<ul>
<li>个人应用<br>
这里使用gulimall项目应用</li>
</ul>
<h2 id="postman调试接口">Postman调试接口</h2>
<ol>
<li>
<p>在gitee中创建第三方应用<br>
<strong>应用主页:</strong> 用户项目的主要页面,一般不直接跳转到主页,还需要回调地址再次发送后获取access_token<br>
<strong>应用主页回调地址:</strong> 用户授权后,码云回调到应用,并且回传授权码的地址。【码云会返回一个<code>code</code>值作为标识码,作为后续动作的标识:如获取用户数据,对开放权限操作等】即gulimall项目中http://gulimall.com/oauth2.0/gitee/success 能处理到<code>code</code>值的controller<br>
<strong>权限:</strong> 应用对于gitee的权限操作<br>
<img src="https://img2023.cnblogs.com/blog/2185532/202309/2185532-20230910181628685-1169341728.png" alt="gitee授权登录1" loading="lazy"></p>
</li>
<li>
<p>获取code值</p>
</li>
</ol>
<ul>
<li>在postman中填好参数,然后把完整的请求路径复制到浏览器中发送,<strong>保存返回的code值</strong><br>
(postman返回值不好查看到code值,如果要多次请求,记得清楚浏览器中的cookie)</li>
<li>请求地址为:https://gitee.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code<br>
<img src="https://img2023.cnblogs.com/blog/2185532/202309/2185532-20230910182951343-439684182.png" alt="gitee授权登录2" loading="lazy"><br>
请求,授权登录后会跳转到redirect_url提供的地址,并且在浏览器的url栏会返回<code>code=xxxxxx</code>值,这就是gitee提供的的uuid</li>
</ul>
<blockquote>
<p>redirect_url地址可以是<code>创建应用</code>时候的主页地址也可以是回调地址,主要是后续能处理code值。建议写回调地址</p>
</blockquote>
<ol start="3">
<li>获取access_token令牌</li>
</ol>
<ul>
<li>虽然跳转redirect_url地址是随意填写的,但此时gitee还没给予用户信息,还需要获取access_token令牌去获取用户的数据。<strong>保存返回access_token</strong></li>
<li>请求地址:https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}<br>
❗ 注意:这里请求为<code>post</code>请求<br>
<img src="https://img2023.cnblogs.com/blog/2185532/202309/2185532-20230910184018906-2057268583.png" alt="gitee授权登录3" loading="lazy"></li>
</ul>
<ol start="4">
<li>获取用户信息</li>
</ol>
<ul>
<li>请求地址:https://gitee.com/api/v5/user?access_token={access_token}<br>
<img src="https://img2023.cnblogs.com/blog/2185532/202309/2185532-20230910185729111-1754871741.png" alt="gitee授权登录4" loading="lazy"></li>
</ul>
<h2 id="业务代码参考">业务代码参考</h2>
<p>gitee第三方授权登录流程图:<br>
<img src="https://img2023.cnblogs.com/blog/2185532/202309/2185532-20230913004923870-1210570436.png" alt="gulimall社交登录流程图" style="zoom: 80%"></p>
<h3 id="操作步骤">操作步骤:</h3>
<ol>
<li>引入http工具类<br>
(引入引都没影响,为了方便)</li>
</ol>
<blockquote>
<ul>
<li>HttpUtils请从</li>
</ul>
<p>https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java下载</p>
<ul>
<li>
<p>相应的依赖请参照</p>
<p>https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml</p>
</li>
</ul>
</blockquote>
<ol start="2">
<li>创建OAuth2Controller做请求处理</li>
</ol>
<pre><code class="language-java">/**
* 社交登录请求
*/
@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",client_id);
map.put("redirect_uri","http://auth.gulimall.com/oauth2.0/gitee/success");
map.put("client_secret",client_secret);
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";
}
}
}
</code></pre>
<p>3.给表usm_member添加字段<code>social_id</code>,<code>access_token</code>,<code>expires_in</code></p>
<blockquote>
<p>备注:正常逻辑,应该对每个授权应用做表单。但该练手项目为了避免麻烦,直接在usm_member表中添加social_id,access_token,expires_in三个字段【默认授权应用之间的用户id都不一样。】</p>
</blockquote>
<br>
4. 远程调用member服务,做注册/登录用户功能
```java
//MemberController.java
//登录功能【社交登录】
@PostMapping("/oauth2/login")
public R oauth2Login(@RequestBody SocialUser socialUser) throws Exception {
<pre><code> 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());
}
}
</code></pre>
<pre><code>
```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());
}
}
</code></pre>
<p>5.页面渲染,发送请求</p>
<pre><code class="language-html"><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>
</code></pre><br><br>
来源:https://www.cnblogs.com/bingo39/p/17691045.html
頁:
[1]