app授权和小程序授权

这篇具有很好参考价值的文章主要介绍了app授权和小程序授权。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(1)小程序端调用 wx.login方法获取用户登录凭证code,将code发送给小程序后台服务器;服务器调用登录凭证校验接口(需要传参appid+appsecret+code),进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等,将这些信息存入缓存中。
(2)点击button按钮触发获取微信手机号弹框!
(3)绑定微信账号,存在相应手机号账号时自动登录;不存在时自动创建

app授权和小程序授权,协议开发,逆向,软件开发,小程序,apache,java

1.App登录,如果没有绑定过,重新绑定,es_third_login插入一条记录,并且要存unionId字段
2.APP登录,如果之前绑定过,并且之前的es_third_login表没有存unionId,则更新原数据存入unionId
3.小程序登录,如果之前APP未授权登录,没有存入unionId,首次授权的时候,会在es_third_login插入一条记录
4.小程序登录,如果之前APP授权登录过,存过unionId,那么就直接登录,不会插入数据。

小程序和APP的unionId是相同的,小程序和APP微信联合登录,是通过unionId实现的。只要es_third_login表中同一个会员存在unionId就可以直接登录。

App登录: 调用 thirdLoginSubmit接口

小程序登录: 调用thirdLoginSubmit接口

授权登录:调用getUnionId接口获取到UnionId调用thirdLoginSubmit接口;

thirdLoginSubmit登录接口:

@Override
public BaseResponse<Map<String,Object>> thirdLoginSubmit(@RequestBody ThirdLoginInfoRequest request){
try {
if(request==null){
return MessageResponse.messageResponse("500","false","shop.requestParam.empty",null);
}
String deviceId=request.getDeviceId();
String pluginId=request.getPluginId();
String openId=request.getOpenId();
String appType=request.getAppType();
String unionId = request.getUnionId();
ThirdLogin thirdLogin = thirdLoginService.find(pluginId, openId);
ThirdLogin thirdLoginByUnionId = null;
if (thirdLogin == null){
thirdLoginByUnionId = thirdLoginService.findByUnionId(unionId);
}else{
thirdLoginByUnionId = thirdLogin;
}
HashMap<String, Object> retMap = new HashMap<String, Object>();
if(thirdLoginByUnionId!=null){
Member member = memberService.find(thirdLoginByUnionId.getMember());
Map<String, Object> result = registerMemberUtil.loginCheck(member, RegisterMemberUtil.Type.app, deviceId, appType, request.getAppVersion());
if("error".equals(result.get("type"))){
return MessageResponse.messageResponse("500", "false", result.get("message").toString(), null);
}else {
member=(Member)result.get("member");
}
//老账户unionId为空的,存入unionId
if(StringUtils.isBlank(thirdLoginByUnionId.getUnionId())){
thirdLoginByUnionId.setUnionId(request.getUnionId());
thirdLoginByUnionId.setLastModifiedDate(new Date());
thirdLoginService.update(thirdLoginByUnionId);
}
VipDto vipDto = new VipDto();
vipDto.setMessageId(UUID.randomUUID().toString().replace("-",""));
vipDto.setMemberId(member.getId());
vipDto.setAppType(member.getAppType());
vipDto.setDeviceId(member.getDeviceId());
vipDto.setMessageType(MessageType.login);
loginProducer.send(GsonUtil.toJson(vipDto));
ckToReceiptProducer.send(vipDto);
retMap.put("root", "login");
String appToken=JWTUtils.createAppToken(member.getId(),member.getPassword(),member.getDeviceId(),member.getAppLoginDate());
if(StringUtils.isNotEmpty(appToken) && appToken.startsWith("CharlesKeith ")){
RedisUtils.set(APP_TOKEN + member.getId(), appToken);
appToken=appToken.replaceFirst("CharlesKeith ","");
}
retMap.put(Constants.TOKEN_PARAMETER_NAME, appToken);
retMap.put(Constants.USER_ID, member.getId());
retMap.put(Constants.USERNAME, member.getUsername());
retMap.put(Constants.USERTYPE, member.getType().name());
retMap.put(Constants.REGISTER_LOCATION, member.getRegisterLocation());
retMap.put(Constants.MOBILE, member.getMobile());
retMap.put("valid",valid(member.getId()));
//添加购物车
addCart(request,member);
}else {
retMap.put("root", "bindOrRegister");
}
return BaseResponse.successResponse(retMap);
}catch (Exception e){
e.printStackTrace();
}
return BaseResponse.errorResponse();
}
首先从request当中获取到unionId,pluginId,openId,先根据pluginId,和openId查询第三方绑定信息,根据pluginId和openId查询到的第三方绑定信息为空则根据unionId查询第三方绑定信息

如果查询到的第三方绑定信息为空则返回一个map,封装"root":"bindOrRegister"信息给前端;

如果查询到的第三方绑定信息不为空则:从第三方绑定信息中获取到memberId查询会员信息,对会员信息进行登录校验,校验第三方登录信息是否为空,为空的话把request中的unionid,修改时间跟新保存第三方信息.

异步调用登录活动发劵,同步小票信息,封装"root","login"到map中生成token信息,把token和会员信息封装到map当中返回给前端,跟新购物车信息;

thirdBindOrRegister第三方登录或注册接口:

@Override
public BaseResponse<Map<String,Object>> thirdBindOrRegister(@RequestBody ThirdLoginInfoRequest request){
try {
if(request==null){
return MessageResponse.messageResponse("500","false","shop.parameter.notempty",null);
}
String mobile=request.getMobile();
String captcha=request.getCaptcha();
VerificationCodeRequest codeRequest=new VerificationCodeRequest();
codeRequest.setPhoneNumber(mobile);
VerificationCodeResponse codeResponse = null;
BaseResponse<VerificationCodeResponse> verificationCode = smsClient.getVerificationCode(codeRequest);
if(verificationCode!=null && "true".equals(verificationCode.getStatus())){
codeResponse=verificationCode.getResult();
}
if(codeResponse==null || !codeResponse.getVerifyCode().equals(captcha)){
return MessageResponse.messageResponse("500","false","shop.code.wrong",null);
}
String pluginId=request.getPluginId();
String deviceId=request.getDeviceId();
String openId=request.getOpenId();
String appType=request.getAppType();
String unionId = request.getUnionId();
//小程序不需要传openId
if(!"wx".equals(appType)){
if(StringUtils.isBlank(pluginId) || StringUtils.isBlank(openId)){
return MessageResponse.messageResponse("500","false","shop.common.invalid",null);
}
}
Member member = memberService.findByMobile(mobile);
if(member!=null){
ThirdLogin thirdLogin = thirdLoginService.findByPluginId(pluginId, member.getId());
if(Validator.isNotNullOrEmpty(thirdLogin) && Validator.isNotNullOrEmpty(thirdLogin.getOpenId()) && thirdLogin.getOpenId().equals(openId)){
return MessageResponse.messageResponse("500","false","shop.thirdAccount.error",null);
}
Map<String, Object> checkResult = registerMemberUtil.loginCheck(member, RegisterMemberUtil.Type.app, appType, null,request.getAppVersion());
if(checkResult.get("type").equals("error")){
return MessageResponse.messageResponse("500","false",checkResult.get("message").toString(),null);
}else{
member=(Member) checkResult.get("member");
}
VipDto vipDto=new VipDto();
vipDto.setMessageId(UUID.randomUUID().toString().replace("-",""));
vipDto.setMemberId(member.getId());
vipDto.setDeviceId(member.getDeviceId());
vipDto.setAppType(member.getAppType());
vipDto.setMessageType(MessageType.login);
loginProducer.send(GsonUtil.toJson(vipDto));
ckToReceiptProducer.send(vipDto);
}else{
// 注册操作(没有密码)
member=new Member();
member.setCreatedDate(new Date());
member.setLastModifiedDate(new Date());
member.setRegisterLocation(Constants.REGISTER_APP);
member.setMemberRank(memberRankService.findDefault().getId());
member.setAppLoginDate(new Date());
member.setMobile(mobile);
member.setDeviceId(deviceId);
member.setAppType(appType);
member.setType(MemberType.normal);
member.setPoint(Long.valueOf(0L));
member.setBalance(BigDecimal.ZERO);
member.setAmount(BigDecimal.ZERO);
member.setIsLocked(Boolean.valueOf(false));
member.setIsEnabled(Boolean.valueOf(true));
member.setLoginFailureCount(Integer.valueOf(0));
member.setAppVersion(request.getAppVersion());
Map<String,Object> checkResult = registerMemberUtil.registerCheck(member, RegisterMemberUtil.Type.app,null);
if(checkResult.get("type").equals("error")){
return MessageResponse.messageResponse("500","false",checkResult.get("message").toString(),null);
}else {
member = (Member) checkResult.get("member");
}
Member sourceMember = memberService.saveAndReturn(member);
VipDto vipDto=new VipDto();
vipDto.setMessageId(UUID.randomUUID().toString().replace("-",""));
vipDto.setMemberId(sourceMember.getId());
vipDto.setMessageType(MessageType.register);
ckToReceiptProducer.send(vipDto);
}
ThirdLogin thirdLogin=new ThirdLogin();
thirdLogin.setCreatedDate(new Date());
thirdLogin.setLastModifiedDate(new Date());
thirdLogin.setMember(member.getId());
thirdLogin.setOpenId(openId);
thirdLogin.setPluginId(pluginId);
thirdLogin.setUnionId(unionId);
thirdLoginService.save(thirdLogin);
HashMap<String, Object> retMap = new HashMap<String, Object>();
String appToken=JWTUtils.createAppToken(member.getId(),member.getPassword(),member.getDeviceId(),member.getAppLoginDate());
if(StringUtils.isNotEmpty(appToken) && appToken.startsWith("CharlesKeith ")){
RedisUtils.set(APP_TOKEN + member.getId(), appToken);
appToken=appToken.replaceFirst("CharlesKeith ","");
}
retMap.put("root", "login");
retMap.put(Constants.MOBILE, member.getMobile());
retMap.put(Constants.USERTYPE, member.getType().name());
retMap.put(Constants.TOKEN_PARAMETER_NAME, appToken);
retMap.put(Constants.USER_ID, member.getId());
retMap.put(Constants.USERNAME, member.getUsername());
retMap.put(Constants.REGISTER_LOCATION, member.getRegisterLocation());
retMap.put("valid",valid(member.getId()));
//添加购物车
addCart(request,member);
return BaseResponse.successResponse(retMap);
}catch (Exception e){
e.printStackTrace();
return BaseResponse.errorResponse();
}
}

当前端调用登录返回map为"root":"bindOrRegister"信息时调用接口

首先校验request信息不为空,从request中获取到手机号和验证码,对验证码进行校验。从request中获取到pluginId,deviceId,openId,appType,unioId,根据appType判断当不为微信小程序登录时候对pluginId.openId校验不能为空

根据手机号获取到会员信息,会员信息不为空时进行登录操作: 根据pluginId和会员Id查询到该会员的第三方绑定信息,把第三方中的openId与request获取的openId比较是否相同来判断是否已经绑定过该信息;

                                                                                                    对会员信息进行登录校验,异步调用活动发劵,小票同步信息, 根据会员信息和request的信息生成第三方绑定信息保存,生成token,返回"root":"login"和token信息和会员信息到Map中返回给前端跟新购物车信息

                                                  会员信息为空时进行注册操作:  根据request信息生成新会员信息,对会员信息进行注册校验保存会员信息,调用异步小票同步信息。根据会员信息和request的信息生成第三方绑定信息保存,生成token,返回"root":"login"和token信息和会员信息到Map中返回给前端更新购物车信息

以下逻辑是小程序授权登录

一、获取unionId
通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程
 
请求地址
 
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数
属性    类型    默认值    必填    说明
appid    string        是    小程序 appId
secret    string        是    小程序 appSecret
js_code    string        是    登录时获取的 code
grant_type    string        是    授权类型,此处只需填写 authorization_code
返回值
Object
返回的 JSON 数据包

属性    类型    说明
openid    string    用户唯一标识
session_key    string    会话密钥
unionid    string    用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明。
errcode    number    错误码
errmsg    string    错误信息
2.用户未关注公众号等相关主体账号时,通过code获取不到unionId时,则通过session_key、encryptedData、iv获取unionId

encryptedData    string    包括敏感数据在内的完整用户信息的加密数据
iv    string    加密算法的初始向量
接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。 解密算法如下:

对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
对称解密的目标密文为 Base64_Decode(encryptedData)。
对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
如接口 wx.getUserInfo 敏感数据当中的 watermark:

{
    "openId": "OPENID",
    "nickName": "NICKNAME",
    "gender": GENDER,
    "city": "CITY",
    "province": "PROVINCE",
    "country": "COUNTRY",
    "avatarUrl": "AVATARURL",
    "unionId": "UNIONID",
    "watermark":
    {
        "appid":"APPID",
        "timestamp":TIMESTAMP
    }
}
a.首先通过code获取到session_key

b.通过session_key解密,从解密后的接送中提取unionId

二、获取session_key
小程序点击个人中心,首先会调thirdLogin/getSessionKey,后端通过传递的code获取到session_key保存到redis,用于后续获取手机号
session_key的过期时间通过小程序的checkSession检查,不需要后端做任何操作,获取到的session_key也不需要返还给小程序,只需自己保存即可
三、获取手机号
文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

小程序调thirdLogin/getPhoneNumber,传给后端encryptedData,iv。后端通过之前redis保存的session_key解密数据
解密坑很多(前端必须将传递的数据通过encode处理,防止数据传递丢失,同时encryptedData,iv必须保证16个字节长度)
解密成功返给前端手机号,前端拿到手机号后通过手机号授权快速登录
获取得到的开放数据为以下 json 结构:

{
    "phoneNumber": "13580006666",
    "purePhoneNumber": "13580006666",
    "countryCode": "86",
    "watermark":
    {
        "appid":"APPID",
        "timestamp": TIMESTAMP
    }
}
参数    类型    说明
phoneNumber    String    用户绑定的手机号(国外手机号会有区号)
purePhoneNumber    String    没有区号的手机号
countryCode    String    区号
四、小程序通过手机号快速授权登录
通过手机号查询会员(手机号为之前解密传给前端的手机号)
会员存在,直接将会员数据返回给小程序
会员不存在,直接注册新会员,并将数据返回给小程序(小程序快捷登录的不绑定第三方)
五、开发中的坑
前端传过来的code,通过后台请求微信接口的时候,code只能用一次,重复使用小程序报错msg:code been used, hints
获取手机号的时候,需要用到session_key,在刚开始通过code获取到session_key的时候,可以放到redis里,等下次用的时候直接在redis拿,切忌不可将session_key返回前端然后在获取手机号的时候通过前端传递
保存session_key的到redis时候,一定要记得redis的key要唯一,最开始我就是直接保存的,导致多个用户同时登录时候,只有一个能登录成功,其实是因为他们共用了同一个session_key。一定要加以区分,可以把openId传过来放入key中作为唯一约束
也许前端生成的加密数据和加密向量是正常的,直接复制给我们调微信接口可以获取到数据,但是在传递的时候可能会丢失字符,比如%等字符会解析成其他字符,可通过base64处理文章来源地址https://www.toymoban.com/news/detail-841239.html

到了这里,关于app授权和小程序授权的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uniapp 微信小程序之隐私协议开发

    官网通知:https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/PrivacyAuthorize.html 1、配置 __usePrivacyCheck__: true ;位置 manifest.json : 2、用户隐私保护指引中添加对应的权限,提交审核,位置:微信公众平台-设置-服务内容声明-用户隐私保护指引-更新 3、自定义弹框

    2024年02月05日
    浏览(48)
  • 【软件逆向】如何逆向Unity3D+il2cpp开发的安卓app【IDA Pro+il2CppDumper+DnSpy+AndroidKiller】

    课程作业要求使用反编译技术,在游戏中实现无碰撞。正常情况下碰撞后角色死亡,修改为直接穿过物体不死亡。 il2CppDumper。 DnSpy。 IDA Pro。 AndroidKiller。 一、使用il2CppDumper导出程序集 将{my_game}.apk后缀修改为{my_game}.zip,使用解压工具解压至文件夹{my_game}。(my_game为apk的文件

    2024年02月05日
    浏览(42)
  • App和小程序要备案,独立开发者如何推广应用?独立APP怎么赚钱?

    现在国内个人开发者的 App、小程序都需要完成备案才能发布 ,已经发布的也需要进行备案,否则将不再支持网络接入,应用商店也有可能直接把应用下架。 AdSet官网 | 聚合SDK广告变现平台-上海神蓍信息科技有限公司 备案能在一定程度上拦截大部分流氓软件,对独立开发者来

    2024年02月04日
    浏览(58)
  • 【源码系列】打车系统开发支持APP公众号H5和小程序

    用户注册登录:未注册的手机号将自动创建账号 通过好友的邀请链接进行注册,将会绑定上下级关系 也可以注册的时候输入好友的邀请码,也可以绑定关系 用户充值: 用户下单支付时,可以选择余额或者其他支付方式。 充值一定金额可获得优惠券,优惠券在管理端设置。

    2024年02月05日
    浏览(53)
  • 微信小程序隐私协议自定义页面(弹窗)开发流程以及低版本兼容

    这里我选择的是全局监听,进入小程序就会监控用户有没有同意,没有则进行弹窗,不同意则关闭,这个逻辑可以根据自己需要随便修改。 发现有很多人根据自己调试基础库来排查自己涉不涉及,你的小程序是否涉及隐私协议整改,还是看有没有调用涉及隐私接口,如果有,

    2024年01月16日
    浏览(61)
  • 微信小程序审核,隐私协议中开发者处理信息填写的内容参考

    为了分辨用户,开发者将在获取你的明示同意后,收集你的微信昵称、头像 为了显示距离,开发者将在获取你的明示同意后,收集你的位置信息。 开发者收集你的地址,用于获取位置信息。 开发者收集你的发票信息,用于维护消费功能。 为了用户互动,开发者将在获取你的

    2024年02月08日
    浏览(61)
  • 【Android 逆向】程序员高危开发方向 ( 违法软件类型 | 赌博游戏 | 色情类应用 | 涉及金融类软件 | 爬虫类软件 | 区块链货币 | 甄别是否合法 )

    棋牌类 游戏开发 , 写这类游戏的程序员 很容易被抓 , 只要 涉及到了 充值 以及 提现 , 就是涉嫌赌博 ; 常见的 就是 麻将类游戏 , 纸牌类游戏 , 具体的地方麻将或扑克玩法 , 德州扑克 , 21 点 , 老虎机 等 类型的 游戏 ; 抽卡类的游戏 , 充值 然后 赌概率 , 比如原神这种 , 只充值

    2024年01月19日
    浏览(47)
  • 14-5_Qt 5.9 C++开发指南_基于HTTP 协议的网络应用程序

    Qt 网络模块提供一些类实现 OSI 7 层网络模型中高层的网络协议,如 HTTP、FTP、SNMP等,这些类主要是 QNetworkRequest、QNetworkReply和QNetworkAccessManager。 QNetworkRequest 类通过一个URL 地址发起网络协议请求,也保存网络请求的信息,目前支持 HTTP、FTP 和局部文件 URLs的下载或上传。 QNe

    2024年02月13日
    浏览(54)
  • 软件‘小程序‘前台开发软件定制的知识|app网站搭建

    软件,小程序,前台开发软件定制的知识         随着互联网的快速发展,软件,小程序,前台开发软件定制已经成为了企业必备的工具。它可以帮助企业更好地管理业务,提高效率,增强用户体验。那么,什么是软件,小程序,前台开发软件定制呢?下面就让我来为大家简

    2024年02月05日
    浏览(47)
  • Python-Python高阶技巧:HTTP协议、静态Web服务器程序开发、循环接收客户端的连接请求

    当前版本号[20231114]。 版本 修改说明 20231114 初版 1.1 网址的概念 网址又称为URL,URL的英文全拼是(Uniform Resoure Locator),表达的意思是 统一资源定位符 ,通俗理解就是网络资源地址。 URL地址:https://www.itcast.com/18/1122/10/E178J2O4000189FH.html 1.2 URL的组成 域名 : IP地址的别名 ,它是用

    2024年02月04日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包