微信开放平台:微信扫码登录功能
正式文件:
1.批准流程说明
微信OAu认证登录允许微信用户使用微信id安全登录第三方应用程序或网站,在微信用户授权访问微信OAu的第三方应用程序登录后,第三方可以获取用户的接口调用凭证(access_token),通过ACESS _ TOKEN可以进行微信开放平台认证关系接口调用,从而获得微信用户的基本开放信息
微信OAu授权登录目前支持authorization_CODE模式,适用于拥有server端的应用授权。该模式整体流程为:
① 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
② 通过code参数加上AppID和AppSecret等,通过API换取access_token;
③ 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
第一步:请求CODE
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:;redirect_uri=REDIRECT_URI&response_type=code&SCOPE=SCOPE&state=STATE#wechat_redirect
返回说明
用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数
redirect_uri?code=CODE&state=STATE
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE
例如:登录一号店网站应用 打开后,一号店会生成state参数,跳转到 ;redirect_uri=https%3A%2F%2F;response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect 微信用户使用微信扫描二维码并且确认登录后,PC端会跳转到 ;state=3d6be0a4035d839573b04816624a415e
第二步:通过code获取access_token
通过code获取access_token
;secret=SECRET&code=CODE&grant_type=authorization_code
返回说明
正确的返回:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
错误返回样例:
{"errcode":40029,"errmsg":"invalid code"}
- Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
- access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
- refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。
建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。
第三步:通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:
- access_token有效且未超时;
- 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
对于接口作用域(scope),能调用的接口有以下:
2. 授权流程代码
因为微信开放平台的AppiD和APPSecret和微信公众平台的AppiD和AppSecret都是不同的,因此需要配置一下:
# 开放平台
wec
wec
@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {
//公众号appid
private String mpAppId;
//公众号appSecret
private String mpAppSecret;
//商户号
private String mchId;
//商户秘钥
private String mchKey;
//商户证书路径
private String keyPath;
//微信支付异步通知
private String notifyUrl;
//开放平台id
private String openAppId;
//开放平台秘钥
private String openAppSecret;
}
@Configuration
public class WechatOpenConfig {
@Autowired
private WechatAccountConfig accountConfig;
@Bean
public WxMpService wxOpenService() {
WxMpService wxOpenService = new WxMpServiceImpl();
wxO(wxOpenConfigStorage());
return wxOpenService;
}
@Bean
public WxMpConfigStorage wxOpenConfigStorage() {
WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
wxM());
wxM());
return wxMpInMemoryConfigStorage;
}
}
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WeChatController {
@Autowired
private WxMpService wxMpService;
@Autowired
private WxMpService wxOpenService;
@GetMapping("/qrAuthorize")
public String qrAuthorize() {
//returnUrl就是用户授权同意后回调的地址
String returnUrl = ";;
//引导用户访问这个链接,进行授权
String url = wxO(returnUrl, WxCon, URLEncoder.encode(returnUrl));
return "redirect:" + url;
}
//用户授权同意后回调的地址,从请求参数中获取code
@GetMapping("/qrUserInfo")
public String qrUserInfo(@RequestParam("code") String code) {
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
try {
//通过code获取access_token
wxMpOAuth2AccessToken = wxO(code);
} catch (WxErrorException e) {
log.error("【微信网页授权】{}", e);
throw new SellException(), e.getError().getErrorMsg());
}
//从token中获取openid
String openId = wxM();
//这个地址可有可无,反正只是为了拿到openid,但是如果没有会报404错误,为了好看随便返回一个百度的地址
String returnUrl = ";;
log.info("openid={}", openId);
return "redirect:" + returnUrl + "?openid="+openId;
}
}
请求路径:在浏览器打开
;redirect_uri=http%3A%2F%2F;response_type=code&scope=snsapi_login&state=http%3a%2f%2
获取了openid:openid=o9AREv7Xr22ZUk6BtVqw82bb6AFk
3. 用户登录和登出
@Controller
@RequestMapping("/seller")
public class SellerUserController {
@Autowired
private SellerService sellerService;
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private ProjectUrlConfig projectUrlConfig;
@GetMapping("/login")
public ModelAndView login(@RequestParam("openid") String openid,
HttpServletResponse response,
Map<String, Object> map) {
//1. openid去和数据库里的数据匹配
SellerInfo sellerInfo = (openid);
if (sellerInfo == null) {
map.put("msg", Re());
map.put("url", "/sell/seller/order/list");
return new ModelAndView("common/error");
}
//2. 设置token至redis
String token = UUID.randomUUID().toString();
//设置token的过期时间
Integer expire = Redi;
redi().se, token), openid, expire, TimeUnit.SECONDS);
//3. 设置token至cookie
CookieU(response, CookieCon, token, expire);
return new ModelAndView("redirect:" + ";);
}
@GetMapping("/logout")
public ModelAndView logout(HttpServletRequest request,
HttpServletResponse response,
Map<String, Object> map) {
//1. 从cookie里查询
Cookie cookie = CookieU(request, CookieCon);
if (cookie != null) {
//2. 清除Redis
redi().getOperations().delete, cookie.getValue()));
//3. 清除cookie
CookieU(response, CookieCon, null, 0);
}
map.put("msg", Re());
map.put("url", "/sell/seller/order/list");
return new ModelAndView("common/success", map);
}
}
① 将上一步获取到的openid存入数据库
② 将授权后跳转的地址改为登录地址
//用户授权同意后回调的地址,从请求参数中获取code
@GetMapping("/qrUserInfo")
public String qrUserInfo(@RequestParam("code") String code) {
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
try {
//通过code获取access_token
wxMpOAuth2AccessToken = wxO(code);
} catch (WxErrorException e) {
log.error("【微信网页授权】{}", e);
throw new SellException(), e.getError().getErrorMsg());
}
//从token中获取openid
String openId = wxM();
//授权成功后跳转到卖家系统的登录地址
String returnUrl = ";;
log.info("openid={}", openId);
return "redirect:" + returnUrl + "?openid="+openId;
}
③ 在浏览器请求这个链接:;redirect_uri=http%3A%2F%2F;response_type=code&scope=snsapi_login&state=http%3a%2f%2
第三应用请求使用微信扫码登录,而不是使用本网站的密码:
用户同意授权后登入第三方应用的后台管理系统:
4. Spring AOP校验用户有没有登录
@Aspect
@Component
@Slf4j
public class SellerAuthorizeAspect {
@Autowired
private StringRedisTemplate redisTemplate;
@Pointcut("execution(public * com.*.*(..))" +
"&& !execution(public * com.UserController.*(..))")
public void verify() {}
@Before("verify()")
public void doVerify() {
ServletRequestAttributes attributes = (ServletRequestAttributes) Reque();
HttpServletRequest request = a();
//查询cookie
Cookie cookie = CookieU(request, CookieCon);
//如果cookie中没有token说明已经登出或者根本没有登录
if (cookie == null) {
log.warn("【登录校验】Cookie中查不到token");
//校验不通过,抛出异常
throw new SellerAuthorizeException();
}
//去redis里查询
String tokenValue = redi().ge, cookie.getValue()));
//如果redis中没有对应的openid,同样表示登出或者根本没有登录
if (tokenValue)) {
log.warn("【登录校验】Redis中查不到token");
throw new SellerAuthorizeException();
}
}
}
5. 拦截登录校验不通过抛出的异常
拦截及登录校验不通过的异常,让其跳转到登录页面,扫码登录
@ControllerAdvice
public class SellExceptionHandler {
//拦截登录异常
@ExceptionHandler(value = SellerAu)
public ModelAndView handlerAuthorizeException() {
//拦截异常后,跳转到登录界面
return new ModelAndView("redirect:".concat("; +
"appid=wx6ad144e54af67d87" +
"&redirect_uri=http%3A%2F%2F; +
"oTgZpwenC6lwO2eTDDf_-UYyFtqI" +
"&response_type=code&scope=snsapi_login" +
"&state=http%3a%2f%2"));
}
@ExceptionHandler(value = SellExce)
@ResponseBody
public ResultVO handlerSellerException(SellException e) {
return Re(), e.getMessage());
}
@ExceptionHandler(value = ResponseBankExce)
@ResponseStatu)
public void handleResponseBankException() {
}
}
来源:
1.《微信怎么用二维码登陆不了看这里!微信扫码登录很难吗?5步帮你搞定》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《微信怎么用二维码登陆不了看这里!微信扫码登录很难吗?5步帮你搞定》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/2975813.html