Oauth2.0
OAuth:OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
OAuth2.0:对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前需要显式的向用户征求授权。
微博登录
url实现
- 引导用户到微博的认证地址:
https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
- client_id:微博网站接入提供的 APP KEY;
- redirect_uri:认证后重定向的地址;
- 用户同意授权重定向到上面设置的地址并携带 code:
http://www.gulimall.com/success?code=CODE
; - 使用 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;
- redirect_uri:认证后重定向的地址
http://www.gulimall.com/success
- code:第二步返回的 code 值;
- 返回响应报文:
{
"access_token": "2.00pDpxyGd3J5bEef6b98778e0ZKsu4",
"remind_in": "157679999",
"expires_in": 157679999,
"uid": "6397634785",
"isRealName": "true"
}
通过获取到的access_token请求微博已有权限接口获取用户信息
业务实现
@Slf4j
@Controller
public class OAuth2Controller {
@Autowired
MemberFeign memberFeign;
@GetMapping(value = "/oauth2.0/weibo/success")
public String weibo(@RequestParam("code") String code) throws Exception {
// 根据code换取accessToken
Map<String, String> map = new HashMap<>();
map.put("client_id","704639472");
map.put("client_secret","99ace114599fa9a72fa0cc3b155d0e95");
map.put("grant_type","authorization_code");
map.put("redirect_uri","http://auth.gulimall.com/oauth2.0/weibo/success");
map.put("code",code);
// https://api.weibo.com/oauth2/
// access_token?client_id=704639472&client_secret=99ace114599fa9a72fa0cc3b155d0e95&
// grant_type=authorization_code&redirect_uri=http://gulimall.com/success&code=00e711a97d9ebae92c79f77c2f035d1e
HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<>(), map, new HashMap<>());
// 处理
if(response.getStatusLine().getStatusCode()==200) {
String json = EntityUtils.toString(response.getEntity());
// 此处拿到了社交账号的uid,通过socialUser中的accessToken和uid调用已有权限用户接口,即可获得微博用户信息
SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
// 调用远程服务,查看该社交账号是否第一次登录,第一次登录就注册,否则就是登录
R r = memberFeign.oauthLogin(socialUser);
if(r.getCode()==0) {
MemberRespVo memberRespVo = r.getData("data", new TypeReference<MemberRespVo>(){});
log.info("登录成功,用户信息{}",memberRespVo);
//登录成功跳回首页
return "redirect:http://gulimall.com";
}else {
return "redirect:http://auth.gulimall.com/login.html";
}
}
return "redirect:http://auth.gulimall.com/login.html";
}
}
@Override
public MemberEntity login(SocialUser vo) {
String uid = vo.getUid();
MemberEntity memberEntity = this.getOne(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getSocial_uid, uid));
if(memberEntity!=null) {
// 登录, 更新过期时间和accessToken,同一个用户uid不变
MemberEntity update = new MemberEntity();
update.setId(memberEntity.getId());
update.setAccess_token(vo.getAccess_token());
update.setExpires_in(vo.getExpires_in());
this.updateById(update);
memberEntity.setAccess_token(vo.getAccess_token());
memberEntity.setExpires_in(vo.getExpires_in());
memberEntity.setSocial_uid(vo.getUid());
return memberEntity;
}else {
// 注册
MemberEntity register = new MemberEntity();
register.setCreateTime(new Date());
// 通过微博提供接口获取用户信息
HashMap<String, String> query = new HashMap<>();
query.put("access_token",vo.getAccess_token());
query.put("uid",vo.getUid());
HttpResponse response = null;
try {
response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get", new HashMap<String, String>(), 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");
register.setNickname(name);
register.setGender("m".equalsIgnoreCase(gender)?0:1);
register.setExpires_in(vo.getExpires_in());
register.setAccess_token(vo.getAccess_token());
register.setSocial_uid(vo.getUid());
this.save(register);
}
} catch (Exception e) {
e.printStackTrace();
}
return register;
}