🙆♂️OAuth2:是一种授权框架,仅用于授权代理,针对特定问题的一种解决方案。主要可以解决两个问题,一种是开放系统间的授权,另一种是分布式之间的访问问题。
🙆♂️开放系统间授权:通过向第三方应用授权,可以让第三方应用获得相同的权限从而使其可以执行对其他应用的操作。实现方式:用户密码复制(适用于同一公司内部系统,安全性太低),通用开发者Key(适用于合作商或不同业务部门之间),办法令牌(接近OAuth2的方法,需要考虑管理令牌,颁发令牌与销毁令牌)
🙆♂️分布式访问问题(单点登录):在登录成功后,返回按一定规则生成的字符串,字符串内包含用户信息,通过路径或cookie将字符串传递,后面再发送请求时,每次都带着这个字符串进行发送,当获取到这个字符串时,就可以从其中拿到用户信息。
🙆♂️OAuth2解决方案:令牌机制,生成一定规则的字符串,附带用户信息。
🙆♂️OAuth2并不是协议而是一种解决方案,它提出这种办法来解决问题但并没有规定具体怎么做,像JWT是其中一种生成规则的实现方法。
在此之前的准备工作我们需要注册微信开放平台并且进行开发者资质验证,而后进行创建应用,得到app_id、app_secret、redirect_url,这些信息,验证有些困难可以去看看码上登录。
首先进行配置文件信息的添加,我们打开用户模块的application.yml文件,将我们上面的信息添加到文件中去。
# 微信开放平台配置信息
wx:
open:
app_id: // id应用唯一标识
app_secret: // 密钥
redirect_url: // 回调地址
写个常量类把我们配置文件中的信息拿到以便于后面进行操作。
// spring初始化bean的时候,如果bean实现了InitializingBean接口,
// 会自动调用afterPropertiesSet方法
@Component
public class ConstantWxUtils implements InitializingBean {
@Value("${wx.open.app_id}")
private String appId;
@Value("${wx.open.app_secret}")
private String app_secret;
@Value("${wx.open.redirect_url}")
private String redirect_url;
private static String WX_OPEN_APP_ID;
private static String WX_OPEN_APP_SECRET;
private static String WX_OPEN_REDIRECT_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_OPEN_APP_ID = appId;
WX_OPEN_APP_SECRET = app_secret;
WX_OPEN_REDIRECT_URL = redirect_url;
}
}
一、生成二维码以便扫描
我们可以直接访问tx提供的固定地址,将一些参数信息传入进行请求后,就可以得到一个二维码。是通过https://open.weixin.qq.com/connect/qrconnect这个地址,加问号后拼接参数得到。参数有:appid:设备唯一标识 | redirect_url:使用urlEncode对链接进行处理 | response_type:填code | scope:应用授权作用域,多个作用域用逗号分隔 | state:保持请求和回调的状态,授权请求后原样带回第三方(非必须)。
// 生成微信扫描登录的二维码
@GetMapping("login")
public String getWxCode() {
// 固定地址后拼接参数
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
// 对redirect_url进行URLEncoder编码
String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
try {
redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 填充占位符信息%s
String url = String.format(baseUrl,
ConstantWxUtils.WX_OPEN_APP_ID,
redirectUrl,
"leader");
// 重定向到请求微信的地址
return "redirect:" + url;
}
这个注解使用@Controller,因为@RestController访问url连接会进行格式转换,导致我们访问地址失败,生成二维码失败。
我们上面做了两个操作,第一个通过向地址发送请求信息得到一个二维码,这个二维码包含了我们设置的一些配置信息,第二个是通过扫描这个二维码之后,会调用配置中的域名跳转地址:wx.open.redirect_url。在实际开发中可以直接将配置信息写成公司域名服务器上。但是在本地实现,我们需要修改本地服务端口号,并且将接口地址和域名跳转地址写成一样(这种只是为了测试使用)。
二、获取扫码人的信息 Httpclient json转换
扫描之后会有两个参数传递回来,一个是code(类似于验证码的随机唯一的值),一个是state(临时票据,原样传递)。
http://localhost:8160/api/ucenter/wx/callback?
code=081Vnm0w3MJzvZ2kbh3w3Iq5Mr1Vnm0J&
state=xxxxxx
通过得到的code,同时与id和密钥一起请求wx提供的另一个固定地址,获取到另外两个值分别为:access_token:访问凭证 与 openid:用于区分不同微信的id。
//向认证服务器发送请求换取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;
// 使用http工具类进行http发送get请求
try {
result = HttpClientUtils.get(accessTokenUrl);
} catch (Exception e) {
throw new LeaderException(20001, "获取access_token失败");
}
// 解析json字符串
Gson gson = new Gson();
HashMap map = gson.fromJson(result, HashMap.class);
String accessToken = (String) map.get("access_token");
String openid = (String) map.get("openid");
紧接着还没完,我们还需要再次拿着access_token与openid,访问wx提供的另一个固定地址,这时候我们才能最终得到扫码用户的信息。
// 根据openid查询用户是否曾使用微信登录过
UcenterMember member = memberService.getByOpenId(openid);
if (member == null) {
System.out.println("新用户,注册信息");
// 访问微信的资源服务器,通过accessToken与openid获取用户信息
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
// 使用httpclient发送get请求得到用户信息
String resultUserInfo = null;
try {
resultUserInfo = HttpClientUtils.get(userInfoUrl);
} catch (Exception e) {
throw new LeaderException(20001, "获取用户信息失败");
}
// 解析json字符串 拿到用户头像与昵称 后面添加用户使用
HashMap mapUserInfo = gson.fromJson(resultUserInfo, HashMap.class);
String nickname = (String) mapUserInfo.get("nickname");
String headimgurl = (String) mapUserInfo.get("headimgurl");
总共需要请求三次固定api网址,分别为
请求生成二维码:
"https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
请求获取token与openid:
"https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
请求得到用户信息:
"https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)