把这块理清,以后出去和别人说还能吹个牛皮,嘻嘻🐕
大家有没有发现,现在很多的软件或者网页都可以直接进行QQ登录或者微信登录,更让人疑惑的是登录后,我们社交软件的昵称直接在网页上进行显示了,堂堂腾讯的信息安全就这么堪忧吗?小马哥就那么容易受人欺负吗?
当然大家都知道这是说笑,那其中真正蕴藏着的原理是什么呢❓
那就得从OAuth2这个让人既熟悉又陌生的协议讲起,也不废话一句通俗的话,通俗的图简单带过。
“给应用有限的访问权限,让应用能代表用户去访问用户数据"
想必大🔥看了上面的话和图还有那么的一知半解,那我们直接代码说话,++代码取自我做的在线系统项目++。
代码的用意是,通过微信直接登陆我的在线教育系统,使得用户可以减少注册时的繁琐。
@GetMapping("login")
public String getWxCode()
{
String codeUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s"+
"&redirect_uri=%s"+
"&response_type=code"+
"&scope=snsapi_login"+
"&state=%s"+
"#wechat_redirect";
//回调地址 要编码
String redirectUri = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
try
{
redirectUri = URLEncoder.encode(redirectUri,"UTF-8");
}catch (Exception e){
throw new GuliException(20001,e.getMessage());
}
//设置%s里面的值
String url = String.format(
codeUrl,
ConstantWxUtils.WX_OPEN_APP_ID,
redirectUri,
"atguigu"
);
return "redirect:"+url;
}
第一部分代码是请求微信开放平台获取登录二维码,其中的ConstantWxUtils.WX_OPEN_APP_ID的这个固定值是微信的回调函数,当然这是需要通过注册,一系列的校验才会发放的,++ps:我这个是借用别人的++。具体的流程就是通过请求codeUrl,也就是微信开放平台获取登录二维码,用户登录成功后,可以重定向到我的回调网页中,注意这时候它的身上已经带着code值也就是临时票据了,接下来看下一部分是如何操作的。
@GetMapping("callback")
public String callback(String code,String state)
{
//1 获取code值,临时票据,类似于验证码
//向认证服务器发送请求交换access_token
String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
String accessTokenUrl = String.format(baseAccessTokenUrl,ConstantWxUtils.WX_OPEN_APP_ID,ConstantWxUtils.WX_OPEN_APP_SECRET,code);
String result = null;
try
{
result = HttpClientUtils.get(accessTokenUrl);
//解析json字符串
Gson gson = new Gson();
HashMap map = gson.fromJson(result, HashMap.class);
//2 拿着code请求微信固定的地址,得到两个值 access_token和openid
String access_token = (String) map.get("access_token");
String openid = (String) map.get("openid");
//用户的信息是肯定能获取到的但是不知道是不是存在用户
UcenterMember member = memberService.getOpenIdMember(openid);
if (member==null) //如果用户不存在 再进行接下来的步骤 不然不用浪费时间了额
{
//3 拿着accesstoken 和 openid 再去请求微信提供的固定地址 获得扫码人的信息
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
String userInfoUrl = String.format(
baseUserInfoUrl,
access_token,
openid
);
String userInfo = HttpClientUtils.get(userInfoUrl);
//根据 获取的用户信息 查找数据库中是否已经存在数据库信息 不存在则添加
//先转换数据
HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
String nickname = (String) userInfoMap.get("nickname"); //昵称
System.out.println("+++++++++++++++++++++++++++++++"+nickname);//打印一下昵称
String headimgurl = (String) userInfoMap.get("headimgurl"); //头像
member = new UcenterMember();
member.setAvatar(headimgurl);
member.setNickname(nickname);
member.setOpenid(openid);
//将数据保存进 数据库
memberService.save(member);
}
//用token传递信息
String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
return "redirect:http://localhost:3000?token="+jwtToken;
}catch (Exception e)
{
throw new GuliException(20001,e.getMessage());
}
第二段代码的意思很明显了,就是通过回调的产生的code,和这两个请求认证服务器必须存在的,这两个参数代表了我们的权限,ConstantWxUtils.WX_OPEN_APP_ID,ConstantWxUtils.WX_OPEN_APP_SECRET,拼接成url,目的去认证服务器请求,获得accesstoken只有通过这个token我们才能获取用户的最终信息。++接下来就不用管我的网页的逻辑了,我这个方法是判断用户是否已经存在在数据库中,没存在才继续请求用户的身份信息++。
再往下看,我们通过组合基础的用户信息页面和access_token、openid得到了针对此openid的用户信息请求网页,随后调用httpClient既可以得到用户的确切信息了。
还不清楚❓一张图奉上❗
希望这样通俗的解释能让大家对这个登录方式乃至这个协议的理解进一步加深,如果本篇文章对你有帮助的话,求赞求币求转发,但最重要的是看的开心😊