持续学习&持续更新中...
守破离
【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【18】认证服务02---微博社交登录
微博社交登录
OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
OAuth2.0:对于用户相关的 OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。
Oauth2.0:授权通过后,使用 code 换取 access_token,然后去访问任何开放 API
- code 用后即毁
- access_token 在几天内是一样的
- uid 永久固定
官方版流程:
图示原理
前置准备
进入微博开放平台
登陆微博,进入微连接,选择网站接入
创建自己的应用
进入高级信息,填写授权回调页的地址,我们可以在开发阶段进行测试了
添加测试账号(选做)
进入文档,按照流程测试社交登陆:
- https://open.weibo.com/wiki/首页
- https://open.weibo.com/wiki/授权机制说明
- https://open.weibo.com/wiki/Oauth2/access_token
实现流程
redirect_uri 就是配的 授权回调页
client_id 就是 App Key
在前端引导需要授权的用户到如下地址:
java
<li>
<a href="https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI">
<img style="width: 50px;height: 18px" src="/static/login/JD_img/weibo.png"/>
</a>
</li>
如果用户同意授权,页面跳转至 YOUR_REGISTERED_REDIRECT_URI/?code=CODE
:在我们的项目里就是:http://auth.gulimall.com/oauth2.0/weibo/success?code=47b9213cf5da2b038ee98fc52f34021d
java
@GetMapping("/oauth2.0/weibo/success")
public String weibo(@RequestParam("code") String code) throws Exception {}
拿code换取Access Token:https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
其中client_id=App Key & client_secret=App Secret
java
Map<String, String> headers = new HashMap<>();
Map<String, String> bodys = new HashMap<>();
bodys.put("client_id", "3276999101");
bodys.put("client_secret", "452bbefff4680ac8554b97799a8c12cb");
bodys.put("grant_type", "authorization_code");
bodys.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
bodys.put("code", code);
//1、根据code换取accessToken;
HttpResponse response = HttpUtils.doPost(
"https://api.weibo.com",
"/oauth2/access_token",
headers,
null,
bodys);
//2、处理
if (response.getStatusLine().getStatusCode() == 200) { // 获取到了 accessToken
String json = EntityUtils.toString(response.getEntity());
SocialUserAccessToken accessToken = JSON.parseObject(json, SocialUserAccessToken.class);
String uid = accessToken.getUid();
// 通过uid就知道当前是哪个社交用户
//1)、当前用户如果是第一次进网站,进行自动注册(为当前社交用户生成一个会员信息账号,以后这个社交账号就对应指定的会员账号)
//登录或者注册这个社交用户
//2)、登录成功就跳回首页
return "redirect:http://gulimall.com";
}
拿到Access Token就可以获取用户信息:https://open.weibo.com/apps/3276999101/privilege
比如:根据用户ID获取用户信息:https://open.weibo.com/wiki/2/users/show
java
Map<String,String> query = new HashMap<>();
query.put("access_token", accessToken);
query.put("uid",uid);
HttpResponse response =
HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", new HashMap<>(), query);
if(response.getStatusLine().getStatusCode() == 200){
//查询成功
String json = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = JSON.parseObject(json);
//获取用户信息
String name = jsonObject.getString("name");
String gender = jsonObject.getString("gender");
}
拿到用户信息就可以判断当前社交用户是否已经登录过系统,快速进行注册/登录。
完整代码
java
<a href="https://api.weibo.com/oauth2/authorize?client_id=xxxx&response_type=code&redirect_uri=xxxx">
<img style="width: 50px;height: 18px" src="/static/login/JD_img/weibo.png"/>
</a>
java
/**
* 微博用户授权成功回调
* http://auth.gulimall.com/oauth2.0/weibo/success?code=7d42ee3197927a8807460280d86152cd
* 拿到code换取Access Token:其中client_id=App Key&client_secret=App Secret
* POST:https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
* 拿到Access Token就可以获取用户信息:
* https://api.weibo.com/2/users/show.json?uid=xxxx&access_token=xxxx
*/
@GetMapping("/oauth2.0/weibo/success")
public String weibo(@RequestParam("code") String code) throws Exception {
Map<String, String> headers = new HashMap<>();
Map<String, String> bodys = new HashMap<>();
bodys.put("client_id", "3276999101");
bodys.put("client_secret", "452bbefff4680ac8554b97799a8c12cb");
bodys.put("grant_type", "authorization_code");
bodys.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
bodys.put("code", code);
//1、根据code换取accessToken;
HttpResponse response = HttpUtils.doPost(
"https://api.weibo.com",
"/oauth2/access_token",
headers,
null,
bodys);
if (response.getStatusLine().getStatusCode() == 200) {
//2、获取到了 socialUserAccessToken 进行处理
String json = EntityUtils.toString(response.getEntity());
SocialUserAccessToken socialUserAccessToken = JSON.parseObject(json, SocialUserAccessToken.class);
// String uid = socialUserAccessToken.getUid();
// 通过uid就知道当前是哪个社交用户
//1)、当前用户如果是第一次进网站,进行自动注册(为当前社交用户生成一个会员信息账号,以后这个社交账号就对应指定的会员账号)
R r = memberFeignService.socialLogin(socialUserAccessToken);
if(r.getCode() == BizCodeEnume.SUCCESS.getCode()) {
//登录或者注册这个社交用户
//2)、登录成功就跳回首页
return "redirect:http://gulimall.com";
}
}
return "redirect:http://auth.gulimall.com/login.html";
}
java
@Override
public MemberEntity login(SocialUserAccessToken socialUser) {
//登录和注册合并逻辑
String uid = socialUser.getUid(); // 社交网站用于标识用户的唯一ID
String accessToken = socialUser.getAccess_token();
//1、判断当前社交用户是否已经登录过系统;
MemberDao memberDao = this.baseMapper;
MemberEntity memberEntity = memberDao.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
long expiresIn = socialUser.getExpires_in();
if (memberEntity != null) {
//这个用户已经注册过
MemberEntity update = new MemberEntity();
update.setAccessToken(accessToken);
update.setExpiresIn(expiresIn);
memberDao.updateById(update);
memberEntity.setAccessToken(accessToken);
memberEntity.setExpiresIn(expiresIn);
return memberEntity;
} else {
//2、没有查到当前社交用户对应的记录我们就需要注册一个(将social_id和我们系统的会员id关联起来)
MemberEntity regist = new MemberEntity();
try {
//3、查询当前社交用户的社交账号信息(昵称,性别等)
Map<String, String> query = new HashMap<>();
query.put("access_token", accessToken);
query.put("uid", uid);
HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", new HashMap<>(), query);
if (response.getStatusLine().getStatusCode() == 200) {
//查询成功
String json = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = JSON.parseObject(json);
//获取用户信息
String name = jsonObject.getString("name");
String gender = jsonObject.getString("gender");
//........
regist.setNickname(name);
regist.setGender("m".equals(gender) ? 1 : 0);
//........
}
} catch (Exception e) {}
regist.setSocialUid(socialUser.getUid());
regist.setAccessToken(accessToken);
regist.setExpiresIn(expiresIn);
memberDao.insert(regist);
return regist;
}
}
参考
雷丰阳: Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目.
本文完,感谢您的关注支持!