Springboot学习 -社交登录的实现 OAuth2.0
1.社交登录
由于QQ/微博/github等网站的用户量非常大,别的网站为了简化自我网站的登录与注册逻辑,简化用户注册步骤,引入社交登录功能.
步骤:
- 用户点击其他平台登录按钮
- 引导跳转到平台授权页
- 用户主动点击授权,跳回之前的网页,完成注册.
2. OAuth2.0
- OAth(开放授权):是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容.
- OAth2.0:对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显示的向用户征求授权.
关于OAth2.0协议的授权流程可以参考下面的流程图:
- 其中Client时值第三方应用
- Resoure Owner值用户
- Authorization Server是我们的授权服务器
- Resource Server是API服务器
授权流程:
- A:第三方应用向用户发送申请请求认证(点击社交登录按钮后跳转到授权平台网页).
- B:用户授权(输入社交账户密码/扫码等).
- C: 发送授权请求到第三方服务器(验证登录),使用上一步授权的信息,进行验证.
- D:认证通过,返回访问令牌.
- E:第三方应用使用访问令牌,请求获取保护信息.
- F:认证访问令牌,返回受保护信息.
3. 社交登录的流程实现
1.进入微博开放平台 申请权限.
微博开放平台
登录成功后点击网站接入:
进行身份验证后进入创建新应用界面:
创建完成后点击->我的应用->应用信息->高级信息, 设置回调地址:
到此,权限设置以及地址回调完成,接下来参考文档进行API接口使用:
API文档
2. 社交登录的使用步骤
1. 引导需要授权的用户到如下地址
- client_id :修改为我的应用->应用信息中的App Key
- redirect_uri:修改为授权成功回调的地址
https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
<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>
此时点击页面按钮后,将跳转至微博授权页面:
2. 如果用户同意授权,页面将跳转至重定向页面redirect_uri,并添加参数code=CODE
3. 使用code 换取 Access token
- client_id 为 App Key
- client_secret 为 App Secret
- grant_type 使用默认值authorization_code
- redirect_uri 为重定向网页地址
- code 为上一步授权登录成功返回的code码
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
4.使用获得的 Access token 调用API访问用户信息
在我的应用->接口管理中可以查看具体可用的接口
使用postman测试:
4. SpringBoot 项目整合社交登录
修改页面授权成功后的回调页面:
http://gulimail.com/oauth2.0/weibo/success
<a href="https://api.weibo.com/oauth2/authorize?client_id=1104100881&response_type=code&redirect_uri=http://gulimail.com/oauth2.0/weibo/success">
<img style="width: 50px ;height: 18px;" src="/static/login/JD_img/weibo.png" />
</a>
后端创建一个controller方法接受回调请求:
@GetMapping("/oauth2.0/weibo/success")
public String weibo(@RequestParam("code") String code) throws Exception {
//根据code 换取access token
HashMap<String, String> map = new HashMap<>();
map.put("client_id","");
map.put("client_secret","");
map.put("grant_type","");
map.put("redirect_uri","");
map.put("code",code);
Map<String, String> headers = new HashMap<>();
HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", headers, null, map);
/**
* {
"access_token": "",
"remind_in": "",
"expires_in": ,
"uid": "",
"isRealName": ""
}
*/
if(response.getStatusLine().getStatusCode() == 200){
//成功获取access token
//获取返回值,转换为json格式
String json = EntityUtils.toString(response.getEntity());
//将字符串转换为指定类型
SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
//对不同类型的社交用户进行处理 TODO 调用远程服务
//1.当前用户如果是第一次(使用uid进行判断)进入网站,则应该自动注册.为当前社交用户生成一个会员信息账户,
//1.2调用微信提供的接口,获取社交账号信息,创建账户
HashMap<String, String> map = new HashMap<>();
map.put("access_token",socialUser.getAccess_token());
map.put("uid",socialUser.getUid());
HttpResponse response = HttpUtils.doGet("https://api.weibo.com",
"/2/users/show.json",
"get",
new HashMap<String, String>(),
map);
//设置社交信息
if(response.getStatusLine().getStatusCode() == 200){
//查询成功
String userInfo = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = JSON.parseObject(userInfo);
String name = jsonObject.getString("name");
String gender = jsonObject.getString("gender");
//....所有信息
regist.setNickname(name);
regist.setGender("m".equals(gender)?1:0);
}
//2.如果不是第一次登录,则将数据库中的访问令牌,有效时间字段更新
//登录成功
return "redirect:http://gulimail.com";
}else {
return "redirect:http://auth.gulimail.com/login.html";
}
}else {
return "redirect:http://auth.gulimail.com/login.html";
}
}
m";
}else {
return "redirect:http://auth.gulimail.com/login.html";
}
}else {
return "redirect:http://auth.gulimail.com/login.html";
}
}