漫谈认证与授权
Intro
认证与授权一直以来都是很多人在讨论的话题,之所以想这次谈一谈认证和授权,主要是因为最近看到许多文章都把认证和授权混为一谈,把认证方式当作是授权方式。所以想写篇文章谈谈我眼中的认证与授权。
Authentication
什么是认证?认证是一个尝试解决我是谁的问题的过程。
以一个 HTTP 请求为例,认证就是 尝试 从请求信息中获取用户信息的过程,
有一点需要特别注意:认证并不等于一定有用户信息,有些文章直接把认证等同于有用户信息,再次强调,认证就是认证,一定有用户信息就相当于是要授权了,有用户信息只能说明某种认证方式认证成功了,经过某种方式认证之后,还是没有用户信息,只能说明这种认证方式认证失败,认证失败并不代表授权失败。
认证的方式可以多种多样,而且我们可以同时使用多种认证方式:比如说 Cookie 认证、JWT 认证 以及其他自定义 Token 认证,之所以称之为认证方式,是因为他们只提供解决我是谁的解决方案,比如 Cookie 认证会尝试从 HTTP 请求携带的 Cookie 信息中获取用户信息,而 JWT 则是从 Authorization 请求头中的 Bearer Token 获取用户的信息,自定义的Token 也类似。
甚至我们可以做一些扩展,做一些不一样的认证,比如说根据 Header/QueryString Authentication,我在我们的项目里就是这么做的,网关解析出用户信息之后转发给下游服务的请求会把用户信息放在请求头里,我们自定义了一个 HeaderAuthentication
从请求头中获取用户的信息,我们下游服务就可以用 HeaderAuthentication
替换原来使用的 JWT 认证,这样 JWT 只需要在网关处认证一次即可,下游服务不再需要验证 token 的有效性以及解析这个 token。
之前提供了一个开源版本的 Header/QueryString Authentication 的实现,实现源码:https://github.com/WeihanLi/AspNetCorePlayground/tree/master/WeihanLi.AspNetCore.Authentication
Authorization
什么是授权?授权顾名思义就是授予权限,允许查看或进行某种操作。
授权是尝试对用户授予访问或操作权限的过程
如果一个资源是允许匿名访问的,那么无论认证成功与否,无论有没有用户信息,都是可以授权访问的
如果一个资源是需要用户有某个角色(Manager)才能访问的,那么首先我们应该先通过认证获取用户的信息,再判断用户是否有这个角色,如果有这个角色则允许授权,否则都不应授权访问。
如果认证失败就没有用户信息,没有用户信息,自然不可能具备 Manager 的角色,这时候就不应该授权访问,如果用户没有认证成功,则需要用户提供有效的认证信息(用户可能没有提供认证信息,也有可能是 token 过期等认证信息无效的错误),这时一般 Web 框架会返回
401 Unauthorized
,如果用户认证成功了,但是没有相应的角色
Manager
,这种情况 Web 框架一般会返回403 Forbidden
如果用户认证成功了,并且拥有
Manager
的角色,则说明用户是有权限访问资源的,这时应该授权用户访问。
一点唠叨:
允许匿名访问、需要用户登录才能访问、需要某种角色才能访问等这些都属于授权,不属于认证,就像允许匿名访问,没有用户信息也可以访问,但是并不影响认证的过程,用户认证成功还是有用户信息的。
Summary
认证是一个尝试解决我是谁的问题的过程。
授权是尝试对用户授予访问或操作权限的过程
More
最后安利一下,自己做的一个关于授权的项目 AccessControlHelper
AccessControlHelper
一个基于策略的授权解决方案,最早是基于 asp.net mvc 做的,实现了可以控制对 Action 的访问和页面上某个元素的访问(Conditional Server Render),后来.netcore2.0 发布之后也支持了 .netcore,.netcore 下的支持更多一点,支持 .net core 下的 TagHelper
和 Policy
,现在的实现还有不太好,感兴趣的可以上去看看,欢迎 issue/pr ...
Github: https://github.com/WeihanLi/AccessControlHelper
Reference
https://github.com/WeihanLi/AspNetCorePlayground/tree/master/WeihanLi.AspNetCore.Authentication
https://github.com/WeihanLi/AccessControlHelper