起因于本狗上一个项目本打算采用微信公众号网页授权登录做用户鉴权,但最终因公众号是未认证的订阅号,无权限获取用户信息,所以改变思路,采用登录注册方式实现用户区分。但在开发中,学习了微信网页授权登录流程,特此分享,带你手把手操作,让我们一起捋清授权的逻辑。
约20分钟
公众号:JavaDog程序狗
在公众号,发送【wx】 ,无任何套路即可获得
| 序号 | 分类 | 文章描述 |
|---|---|---|
| 1 | 项目实战 | SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序 |
网页授权接口权限只有服务号或者已认证的订阅号有权限,也就是需要每年缴纳300块钱费用认证过才会有权限,否则无法在正式公众号调用此接口。
? 切记无权限时调用会提示【微信公众号授权scope参数错误或没有scope权限】,只可在测试公众号进行调试!!!
| 序号 | 分类 | 工具 |
|---|---|---|
| 1 | 后端 | IDEA |
| 2 | 前端 | uniapp |
| 3 | 前端 | 微信开发者工具 |
以测试号进行展示操作步骤
切记不要带http,此处地址填写本地ip即可。可在键盘通过【win+R】,输入【cmd】,确定后输入ipconfig,复制出IPv4地址即可。或者启动uniapp后,控制台打印的地址,以上方法仅限本地调试。
如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
通俗来说,就是我们通过微信内置浏览器去访问其他网站时,可以通过微信授权策略,在目标网站可以获取微信用户的基本信息,如昵称,头像等
通过微信内打开csdn分享链接,当跳转到csdn网页时,csdn就可以通过网页授权,直接拿到我们微信的昵称,头像信息等,完成自主授权注册
前端引导用户进入授权页面同意授权,获取code
通过前端获取的code,调用我们自己服务器接口,通过后台使用code调取微信接口,换取access_token(网页授权接口调用凭证),access_token是调用用户信息及其他接口所必需的参数
由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权
开发者可以通过access_token和 openid 拉取用户信息
? 如果看不懂不要划走,下面才是重点讲解
? 如果看不懂不要划走,下面才是重点讲解
? 如果看不懂不要划走,下面才是重点讲解
为了方便理解,画了一个简易流程图,有疑惑别急,下面还有现实列子解释版
举个实际购买苹果手机例子,可能不太贴合,但有助与理解
根据下图进行步骤分析
前端uniapp中新建授权页
页面进入后,onLoad直接跳转微信接口地址,微信方通过appId获取code,并携带code根据redirect_uri返回到当前页面,此刻地址栏中就包含着code信息
跳转前
跳转后
关键代码
//通过微信官方接口获取code之后,会重新刷新设置的回调地址【redirect_uri】,之后会继续进入到onload()方法
location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" +
local + "&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect""
appid :公众号对应的appId
redirect_uri:页面回跳地址,也就是当前页面的地址,此地址也就是在上方准备4中OAuth2.0网页授权【授权回调页面域名】填入的值。微信根据这个回调地址进行携带code回跳。
其他参数可看官方参数说明
1.后端提供接口,入参为上一步的code,通过code调取微信接口换取access_token。此处后端使用了weixin-java-mp组件,方便对接微信接口。
@Api(tags = "网页授权控制器")
@RestController
@RequestMapping("/login")
public class AuthController {
@Resource
private UserService userService;
@ApiOperation(value = "网页授权获取用户基本信息", notes = "网页授权获取用户基本信息")
@GetMapping
public ResponseData login(@RequestParam String code) throws WxErrorException {
return userService.auth(code);
}
}
2.前端带着code,调用1中的/login接口
const res = await this.$api.login({
code
})
if (!res.success) {
uni.$u.toast(res.message)
return
}
// 用户信息
this.userInfo = res.data;
}
将步骤二后端拿到的access_token,调用微信获取用户信息,将用户信息返回给前端
WxOAuth2AccessToken accessToken;
WxMpUser wxMpUser;
try {
// 获取accessToken
accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
log.info("AccessToken={}" + accessToken);
// 获取用户信息
wxMpUser = wxMpService.getUserService().userInfo(accessToken.getOpenId());
log.info("wxMpUser={}", JSONUtil.toJsonStr(wxMpUser));
} catch (WxErrorException e) {
return ResponseData.error(e.getMessage());
}
return ResponseData.success(wxMpUser);
微信中【OAuth2.0网页授权】-授权回调页面域名配置错误
code每次使用换取access_token后便失效,再次调用则会报错,请根据自己业务,进行缓存比较,防止重复调用
本文虽然篇幅长,但是实现功能简单,主要目的是展示网页授权的流程与思路,对于微信对接,本人建议多查看微信官方文档,写的很详细,通读过几遍后就会对疑问点有些许领悟,希望能对大家有所帮助。
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。