oauth2.0授权详解
学习oauth认证之前先回顾一下通过sessionid的会话过程
关于session与cookie的请戳:https://www.cnblogs.com/moran1992/p/10793748.html
那么这种利用session的会话方式会引发哪些问题呢
1.安全问题
常见保存会话方式:cookie,session以及token等等,这里我们将这三种方式的安全性能都简单的分析一下嘿嘿~
cookie:我们了解cookie的安全问题首先从客户端颁发cookie开始,然后通过set-cookie响应给客户端,客户端保存之后下次通信会以默认的方式携带cookie,这种东西是程序员不可控的,这时候会发生一个什么问题,当网页中的一段link代码发生XSS攻击时,会获取到本
地cookie。那么问题来了。为啥?因为cookie默认写到http的headers里,没法控制。那么好,我们退出登录,这时候服务器对cookie怎么操作的,通过set-cookie的方式清空cookie并返回到客户端。这样导致一个问题,已经被劫持了的cookie还能用,这就是为啥cookie不
安全的原因。
session:首先我们要知道,session到底是个啥,我的理解是session就是cookie的另一种形式,同样session是服务器颁发给客户端的,同样通过响应中的set-cookie,但是与此同时服务器还会保存这个session id,本质上都是通过cookie传递,本质上都可以被上诉攻击方式攻击,但是好处在哪,当退出登录的时候会服务器对session id会有个删除操作。这样被劫持的session id其实就没用了,但是不管怎样,承担的风险方式与cookie是一样的。
token:session与cookie都存在风险,那么更好的解决方案是什么呢,就是token,放在后面说。
2.服务器压力过大
session的特点之一就是存在服务器端,请求过多的时候session也会增多,这就会导致服务器的压力过大。
3.分布式session管理困难
现在几乎所有的web应用程序都会采用分布式的处理方案,那么每次一起请求不一定发送到哪个服务器,比如这次请求发送的Server A上并且保存了session,下一个请求我发Server B上了,Server B没有啊,怎么校验,这就会引发另一个问题,分布式下如何共享session。当然现在有好多的方式比如:Session Replication方式(session复制),缓存集中方式管理(将Session集中放在一个服务器上,我们也可以称其session服务器),基于Redis进行session共享等等,很明显服务器压力很大,而且并不好管理。
4.跨域问题
首先啥叫跨域?域名不同,协议不同,或者端口号不同通通称为跨域,跨域产生于浏览器的同源策略,请求发出去了,但是响应被拦截了。携带headers里面的cookie是不可以跨域的,但是authorization可以啊,token存在哪?token就存在authorization里啊,emmmm~好处显而易见。
说了这么多session的缺点,时代总是向前发展的,技术也一样呀,于是乎token诞生了~
什么是token
token可以理解成一个带有User基本信息的令牌,例如每一次会话调用服务器的API时,服务器可以通过token判断是否有权限。
token流程
token种类
id token(不知道干啥用的,没用过,见过存session id的)
access token(用来做权限认证,生命周期相对比较短)
refresh token(用来生成新的access token,生命周期相对比较长)
token特点有哪些
1.安全性能更好
之前列举了cookie和session的安全性能问题,那么token为啥就安全了?首先token是程序员自己写入http headers里的,并不是像cookie一样自动写入http的headers里的,如果没必要的我们不写入,XSS攻击方式是获取不到token的。
2.无状态(多个服务共享,减轻服务器的鸭梨)
token是无状态的,也就是说token并不存入服务器中(如果想存,请便)当服务器认证过后,会生成一个token返回给用户,并且存入浏览器缓存里(localstorage等),接下来的请求会我们会获取这个token并放入authorization内,服务器接收到请求,并解析token来判断当前请求是否有权限调用api,这里引出另一个概念鉴权。
3.跨程序调用(避开同源策略)
当token变成无状态,只要一个token,就可以在任何一个服务器上认证(解析方式必须一致,其实都是代码层面的东西)于是我们可以采用一种设计方式叫,分离认证服务与业务任务。当我们可以通过认证服务器来获取token,然后发送给业务服务器的时候校验token,这时会出现两种方式,第一种是在业务服务器校验token,另一种是毎一次请求通过中间层再发送给认证服务器进行校验,两种设计方式各有优缺点,不管怎样都是实现了跨程序共享token,咦没有跨域问题哦(当然需要服务器配合嘤嘤嘤~)到这里就引出另一个概念,OAuth认证。
什么是OAuth认证
OAuth是一个关于授权(authorization)的开放网络标准,目前的版本是2.0版,即OAuth2.0
OAuth的应用场景
一个公司往往会有很多系统,比如HR系统,你的请假吧,比如公司的内部员工网站,得有业余活动吧,再比如公司好多产品,但是会有个产品是可以登录所有网站的吧,总不能好多产品分成好多认证系统吧,能用就一个会节约多少人力物力呢~这里会引出一个概念SSO(单点登录)SSO其实是一种解决方案,俺们公司的叫AOS系统。这个通过一个系统登录定向到各个产品的授权过程就是OAuth认证。
OAuth认证设计方式(这里列两种,高大上的我也不知道):
业务服务器校验token
优点:相对于第二种不用每一次请求都要通过鉴权服务器,可以保证token的新鲜度。
缺点:效率低。
认证服务器校验token
优点:效率高
缺点:如果是个第三方的鉴权服务token信息更新不及时
整个鉴权过程都是通过access token,由于有效时间比较短,如果我想要半个月登录一次呢,也就说半个月之内不需要重新登录,怎么办refresh token的作用就产生了。
refresh token做了些什么事儿呢
通过获取access token的有效时间,判断当access token马上过期的时候,这时候我可以通过refresh token从权限服务器获取新的access token,这都可以偷摸的做了,反正使用者不会知道。
1.客户端发送refresh token请求
2.服务器发送refresh token
token的实现方式
现有的token解析方式其实并不唯一,但是有个很出名的那就是jwt(json web token)
什么是jwt
可以理解jwt是token的一种规则
jwt的组成
1.Header 2.Payload 3.Signature
jwt的特点(来自阮一峰)
JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
JWT 不加密的情况下,不能将秘密数据写入 JWT。
JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
栗子(github登录本地站点)
技术栈:nodejs
获取github的token过程
1.注册github应用
找到settings
找到OAuths Apps
注册成功
2.获取github授权码
这里我们需要将注册过得client id跟回调函数当做参数传入
handleGitHubLogin() {
let path = `https://github.com/login/oauth/authorize?response_type=code&redirect_uri=${CommonUtil.Config.github.redirect_uri}&scope=user%2Crepo&client_id=${CommonUtil.Config.github.client_id}`;
location.href = path;
}
这时候会跳到github的授权页面
授权成功后会返回一个code(授权码)
通过code clientId clientSecret获取accessToken
router.post("/oAuthValidate", (req, res) => {
let { clientId, clientSecret, code } = req.body;
axios({
method: "post",
url:
"https://github.com/login/oauth/access_token?" +
`client_id=${clientId}&` +
`client_secret=${clientSecret}&` +
`code=${code}`,
headers: {
accept: "application/json"
}
})
.then(tokenResponse => {
let accessToken = tokenResponse.data.access_token;
getGitHubToken(accessToken, res);
})
.catch(e => {
console.log(e);
});
});
由于整个应用程序采用SAP,所以整个流程通过前台获取最合理,但前台获取token必然会出现一个问题就是跨域,那么如何解决前端跨域资源共享问题呢,这里提供一个解决方案就是Gatekeeper,github自己去找吧,使用方式之后补上。
通过accessToken获取User信息
function getGitHubToken(accessToken, res) {
axios({
method: "get",
url: `https://api.github.com/user`,
headers: {
accept: "application/json",
Authorization: `token ${accessToken}`
}
})
.then(result => {
let token = jwt.sign(result.data, "my_token", { expiresIn: "1h" });
util.responseClient(res, 200, 0, "获取github token成功", {
profileInfo: result.data,
accessToken: token
});
})
.catch(e => {
util.responseClient(res, 500, 0, "get github token failed.", {
message: e
});
});
}
这里为了使用jwt,我并没有使用github的accessToken,而是在自己的应用程序里使用了jwt,可以自行选择。
返回给浏览器并且保存到缓存里
再次请求的时候进行token鉴权
app.use(
expressjwt({
secret: "my_token",
credentialsRequired: true, //如果false 则authoriaztion为空时也通过。
getToken: function fromHeaderOrQuerystring(req) {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
var token = req.headers.authorization.split(" ")[1];
return token;
} else if (req.query && req.query.token) {
return req.query.token;
}
return null;
}
}).unless({
path: util.whiteList
})
); function checkPromisition(req, res, next) {
if (1) {
return next();
} else {
util.responseClient(res, 500, 0, "delete github token failed.", {
log: "delete github token failed with http code 401."
});
}
} app.use(function (err, req, res, next) {
if (err.name === "UnauthorizedError") {
util.responseClient(res, 403, 0, "invalid token...", {});
}
}); app.use("/leavemessage",checkPromisition,require("./leavemessage"));
jwt使用方式
引入jwt中间件
const jwt = require("jsonwebtoken");
jwt生成
let token = jwt.sign(result.data, "my_token", { expiresIn: "1h" });
鉴权部分
引入中间件
const expressjwt = require("express-jwt");
具体细节看上面代码吧
这里有些问题首先github并没有给我refresh token,这里是我没找到吗,请知道的大佬指点一二,其次github没有暴露鉴权的接口吗
撤销github的accesstoken方式
1.清缓存
2.手动自己上去清吧
时间不早了,先写到这里吧,如果哪里理解错的欢迎指正,我会很感激不尽的。
你的关注是对我最大的支持~蟹蟹~
oauth2.0授权详解的更多相关文章
- OAuth2.0认证详解
目录 什么是OAuth协议 OAuth2.0是为了解决什么问题? OAuth2.0成员和授权基本流程 OAuth2.0成员 OAuth2.0基本流程 什么是OAuth协议 OAuth 协议为用户资源的 ...
- oauth2.0授权协议
参考文章 一.OAuth是什么? OAuth的英文全称是Open Authorization,它是一种开放授权协议.OAuth目前共有2个版本,2007年12月的1.0版(之后有一个修正版1.0a)和 ...
- windows版mysql8.0安装详解
2018年07月04日 13:37:40 Zn昕 阅读数 6433更多 分类专栏: mysql 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. ...
- Android消息传递之EventBus 3.0使用详解
前言: 前面两篇不仅学习了子线程与UI主线程之间的通信方式,也学习了如何实现组件之间通信,基于前面的知识我们今天来分析一下EventBus是如何管理事件总线的,EventBus到底是不是最佳方案?学习 ...
- OAuth2.0授权
一.什么是OAuth2.0官方网站:http://oauth.net/ http://oauth.net/2/ 权威定义:OAuth is An open protocol to allow secu ...
- Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端 目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Se ...
- 使用DotNetOpenAuth搭建OAuth2.0授权框架
标题还是一如既往的难取. 我认为对于一个普遍问题,必有对应的一个简洁优美的解决方案.当然这也许只是我的一厢情愿,因为根据宇宙法则,所有事物总归趋于混沌,而OAuth协议就是混沌中的产物,不管是1.0. ...
- 微信开发——OAuth2.0授权
微信公众平台最近新推出微信认证,认证后可以获得高级接口权限,其中一个是OAuth2.0网页授权,很多朋友在使用这个的时候失败了或者无法理解其内容,希望我出个教程详细讲解一下,于是便有了这篇文章. 一. ...
- [转载]AxureRP 7.0部件详解(一)
本文为Axure RT7.0教程,本章主要介绍menu菜单.table表格.Tree Widget 树部件三个部件,后续将持续更新...... Menu 菜单 常用案例 网站导航菜单部件通常用于母板之 ...
随机推荐
- 在父页面用Iframe加载子页面时,将父页面的title替换成子页面title
报告管理
- paddlepaddle实现猫狗分类
目录 1.预备工作 1.1 数据集准备 1.2 数据预处理 2.训练 2.1 模型 2.2 定义训练 2.3 训练 3.预测 4.参考文献 声明:这是我的个人学习笔记,大佬可以点评,指导,不喜勿喷.实 ...
- Rust写时复制Cow<T>
写时复制(Copy on Write)技术是一种程序中的优化策略,多应用于读多写少的场景.主要思想是创建对象的时候不立即进行复制,而是先引用(借用)原有对象进行大量的读操作,只有进行到少量的写操作的时 ...
- unimrcp-voice-activity语音检测
研究 unimrcp有一段时间了,其中unimrcp voice acitve的算法,是遭到大家频繁吐槽.今天我们简单的介绍一下unimrcp voice activity 的这个简单粗暴的算法: u ...
- maysql的自增字段
因为mysql中的自增字段与oracle数据库是不一样的,所以在这里唠嗑一下mysql的自增字段 1.添加自增字段 1.1 在创建表时添加 create table emp( empno ) auto ...
- GooglePlay新版排行榜接入
新版本的GMS的api和老版本的有很大的差异,刚接了一下,在这里留一个记号,以便查阅:判定是否已经登录 private static boolean isSignedIn(Cocos2dxActivi ...
- pythonday04数据类型(二)
今日内容: 1.列表 2.元组 3.py2与py3的区别 4解释器/编译器 5.练习题 1.列表 想要表示多个”事物“,可以使用列表 users = ["李邵奇","奇航 ...
- String与new String()的区别
JVM为了提升性能和减少内存开销,避免字符串的重复创建,维护了一块特殊的内存空间——字符串实例池. String赋值的两种方式. 1.String str = "test"; 以这 ...
- webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案
(写在前面,谈谈物联网展会)上次深圳会展中心举行物联网展会,到了展会一看,80%以上的物联网应用都是在搞RFID,室内定位,我一度怀疑物联网落地方案的方向局限性与市场导向,后来多方面了解才明白,展会上 ...
- windbg 使用与技巧
基本知识和常用命令 (1) Windbg下载地址http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx 安装完后执行w ...