当前位置:网站首页>实现H5网页授权
实现H5网页授权
2022-08-09 13:25:00 【Java初学者,请多多指教】
一、基本介绍
️ H5 网页授权的核心:获取 openid(openid 是每个用户针对每个公众号都会产生的一个安全的,识别用户的,唯一标识用户的字符串)
️ 为什么要获取用户的 openid 呢?用于唯一识别一个用户,为了让系统管理员知道是那个微信用户在系统中操作(如:是那个微信用户提交了表单)
二、获取 openid(前端代码)
(1) 创建一个 uniapp 项目



(2) 获取步骤
官方介绍:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
a. 介绍
code: 用户临时登录凭证
上面的链接的核心参数的介绍:
️ ① appid: 应用的唯一标识
️ ② redirect_uri: 获取到 code 后要访问的链接(通常是某个 Controller 接口)
️ ③ scope: ️a. 如果值是 snsapi_base 表示是静默授权(系统悄悄获得用户的 openid,无需用户点击按钮)️ b. 如果值是 snsapi_userinfo 表示是非静默授权(系统弹框让用户点击【确定】按钮后方可获取用户的 openid)
b. 前端代码
在刚刚创建的 uniapp 项目的 App.vue 文件中的 onLoad(应用第一次被用户访问的时候会调用该方法) 中写如下代码
<script>
export default {
onLaunch: function() {
// 用户第一次进入程序的时候自动调用 login 方法
this.login()
},
methods: {
login() {
const appid = 'wxebbeb8968f1c9b29'
const redirectUri = encodeURIComponent(BASE_NETWORK_URI + 'authOpenIds/h5')
const scope = 'snsapi_userinfo'
let url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".concat(appid)
.concat("&redirect_uri=").concat(redirectUri).concat("&response_type=code&scope=").concat(scope)
.concat("&state=STATE #wechat_redirect")
// 访问
window.location.href = url
},
},
}
</script>
<style>
</style>

c. 后端代码
用于获取 openid 的工具类
public class OpenidUtil{
public static final String APP_ID = "wxc436706a34c9dcd8";
public static final String APP_SECRET = "7fe003e0a896420042307f567c58144a";
// Spring 提供的发送 HTTP 请求的工具
private static RestTemplate restTemplate = new RestTemplate();
public static final String ACCESS_TOKEN = "access_token";
public static final String EXPIRES_IN = "expires_in";
public static final String OPEN_ID = "openid";
public static final String REFRESH_TOKEN = "refresh_token";
public static final String SCOPE = "scope";
private static AccessTokenExpiresIn accessTokenExpiresIn;
// 获取普通 access_token 的请求路径
private static String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=gqAPPID&secret=gqAPPSECRET";
private static String authorizeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=gqAPPID&redirect_uri=gqREDIRECT_URI&response_type=code&scope=gqSCOPE&state=gqSTATE#wechat_redirect";
// 获取网页授权 access_token 的请求路径
private static String authorizeTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=gqAPPID&secret=gqSECRET&code=gqCODE&grant_type=authorization_code";
// 拉取用户信息的请求路径
private static String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=gqACCESS_TOKEN&openid=gqOPENID&lang=zh_CN";
/** * 通过 code 值获取网页授权 access_token、openid等 * * @param code 当用户点击同意授权后可获得 * @return 携带返回数据的 Map */
public static Map<String, String> getH5OpenIdAccessTokenByCode(String code) {
HashMap<String, String> resultMap = new HashMap<>();
String url = authorizeTokenUrl.replace("gqAPPID", APP_ID)
.replace("gqSECRET", APP_SECRET)
.replace("gqCODE", code);
String resultStr = restTemplate.getForObject(url, String.class);
JSONObject resultJSON = JSONUtil.parseObj(resultStr);
return createResultMap(resultJSON, ACCESS_TOKEN, EXPIRES_IN, REFRESH_TOKEN, OPEN_ID, SCOPE);
}
/** * 根据 accessToken 和 openid 获取用户信息 * * @param accessToken * @param openid */
public static Map<String, String> getUserInfoByOpenIdAccessToken(String accessToken, String openid) {
String url = getUserInfoUrl.replace("gqACCESS_TOKEN", accessToken)
.replace("gqOPENID", openid);
String userInfoStr = restTemplate.getForObject(url, String.class);
JSONObject returnJSON = JSONUtil.parseObj(userInfoStr);
HashMap<String, String> returnMap = new HashMap<>();
return createResultMap(returnJSON, OPEN_ID, "sex", "language", "city", "province", "country", "headimgurl");
}
/** * 【方法】获取进入授权页面的请求路径 * * @param appid 应用的唯一标识 * @param redirectUri 用户同意授权后跳转的地址(如果用户同意授权, 会跳转到该地址, 并携带参数 code),【类似 controller 的地址】 * @param scope 授权作用域, 有两种取值: snsapi_base(静默授权, 只得 openid)、snsapi_userinfo(弹出授权页面) * @return 进入授权页面的请求路径 */
public static String getAuthorizeUrl(String appid, String redirectUri, String scope) {
return authorizeUrl.replace("gqAPPID", appid == null ? APP_ID : appid)
.replace("gqREDIRECT_URI", redirectUri)
.replace("gqSCOPE", scope)
.replace("gqSTATE", "zgq");
}
/** * 【方法】获取 access_token 以及 expires_in */
private static void getAccessTokenExpiresIn() {
HashMap<String, String> retMap = new HashMap<>();
// 给请求 url 设值
String url = accessTokenUrl.replace("gqAPPID", APP_ID).replace("gqAPPSECRET", APP_SECRET);
// 向 url 发送网络请求, 获得返回值字符串
String resultStr = restTemplate.getForObject(url, String.class);
// 把 resultStr 转换为 JSON 格式
JSONObject resultJSON = JSONUtil.parseObj(resultStr);
String accessToken = resultJSON.get(ACCESS_TOKEN).toString(); // 凭证值
String expiresIn = resultJSON.get(EXPIRES_IN).toString(); // 凭证有效时间
accessTokenExpiresIn = new AccessTokenExpiresIn(accessToken, expiresIn);
}
/** * 【方法】获取 access_token * * @return access_token 值 */
public static String getAccessToken() {
if (accessTokenExpiresIn == null || accessTokenExpiresIn.alreadyExpired())
getAccessTokenExpiresIn();
return accessTokenExpiresIn.getAccessToken();
}
/** * 组建返回值 Map * * @param params Map 的 key 和 value 的名称一样 */
private static Map<String, String> createResultMap(JSONObject resultJSON, String... params) {
HashMap<String, String> resultMap = new HashMap<>();
for (String p : params) {
resultMap.put(p, resultJSON.get(p).toString());
}
return resultMap;
}
/** * 凭证和凭证有效时间类 */
@lombok.Data
private static class AccessTokenExpiresIn {
private String accessToken;
// 过期时间
private long expireTime;
public AccessTokenExpiresIn(String accessToken, String expiresIn) {
this.accessToken = accessToken;
this.expireTime = System.currentTimeMillis() + Integer.parseInt(expiresIn) * 1000;
}
public boolean alreadyExpired() {
return System.currentTimeMillis() > expireTime;
}
}
}
前端的 redirect_uri 就是填写的 authOpenIds/h5,从而获取到 openid
@RestController
@RequestMapping("/authOpenIds")
public class AuthOpenIdController {
/** * 授权后, 持久化 openid (把它保存在数据库中) * 同时也可把 openid 保存到 Session 中 * @param request 使用 request 把 openid 缓存到服务器 session 中 */
@ApiOperation("公众号 h5 授权")
@GetMapping("/h5")
public String h5(String code, String state, HttpServletRequest request) {
String h5OpenId = OpenIdUtil.getH5OpenId(code);
request.getSession().setAttribute("openid", h5OpenId);
System.out.println("h5OpenId: " + h5OpenId);
return "成功获得";
}
}
边栏推荐
猜你喜欢
随机推荐
数据增广
音频基础学习——声音的本质、术语与特性
C语言中的 递归问题 以及将递归改写成非递归。(解析常见的几个递归题目及代码) 求阶乘、求斐波那契、汉诺塔、
操作系统迁移实战之在openEuler上部署MySQL数据库
iptables防火墙
C语言 一维数组和二维数组的定义及使用
响应式pbootcms模板仪表水表类网站
mmdetction
LNMP架构搭建之论坛
group by的工作原理和优化思路
tkiner组件之滚动文本框(scrolledtext )相关操作
C语言 最大公约数,最小公倍数(详细注释代码 一次解决)
pytest 基础认知
客户端连接rtsp的步骤
零基础学习CANoe Panel 设计目录
Spark GC日志分析
系统可扩展性思考
pytest 之 fixture的定义及作用域
pytest 之 重运行机制与测试报告
RobotFramework 之 用户关键字









