权限认证基础

1. 认证(Authentication)和授权(Authorization)的区别?

这是一个很多人都会混淆的问题。

简单点:

  • 认证(Authentication):你是谁
  • 授权(Authorization):你有权限干什么

正式点:

  • Authentication(认证):是验证您的身份的凭据(例如用户名/用户ID和密码),通过这个凭据,系统得以知道你是谁。也就是说系统存在你这个用户。所以,Authentication 被称为身份/用户验证

     /**
         * 用户认证
         *
         * @param authenticationToken 身份认证 token
         * @return AuthenticationInfo 身份认证信息
         * @throws AuthenticationException 认证相关异常
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String username = (String) token.getPrincipal();
            if (!"javaboy".equals(username)) {
                throw new UnknownAccountException("账户不存在!");
            }
            return new SimpleAuthenticationInfo(username, "123", getName());
        }
    
  • Authorization(授权):发生在Authentication(认证)之后。授权主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问,比如admin,有些对系统资源操作比如删除,添加、更新只能特定人才有

    /**
     * 授权模块,获取用户角色和权限
     *
     * @param token token
     * @return AuthorizationInfo 权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection token) {
        String username = JWTUtil.getUsername(token.toString());
    
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    
        // 获取用户角色集
        Set<String> roleSet = userManager.getUserRoles(username);
        simpleAuthorizationInfo.setRoles(roleSet);
    
        // 获取用户权限集
        Set<String> permissionSet = userManager.getUserPermissions(username);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }
    

2. 什么是Token?什么是JWT?如何基于Token进行身份验证?

2.1 为什么要使用Token/session 的缺点

  1. session 保存在内存中,随着使用者增多,开销大
  2. 分布式 session 还会面临session 共享问题
  3. CSRF: cookie 如果被拦截,使用者就会很容易受到跨站伪造请求的攻击

我们知道session 可以用来鉴别用户的身份,我们Session 信息需要保存一份在服务端。这种方式会带来一些麻烦,比如需要我们保证保存session 信息的服务器的可用性,不适合移动端(依赖Cookie)等等

移动端有Cookie,但还是需要手动实现cookie持久化。默认是非持久化生命周期跟app保持一致。还需要再写拦截器每次封装进请求header

有没有一种不需要自己存放 Session 信息就能实现身份验证的方式呢?使用 Token 即可!JWT (JSON Web Token) 就是这种方式的实现,通过这种方式服务器端就不需要保存 Session 数据了,只用在客户端保存服务端返回给客户的 Token 就可以了,扩展性得到提升。

2.2 什么是JWT

JWT(JSON Web Token) 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。

JWT 由3部分构成

  1. Header:描述JWT 的元数据。定义了生成签名的算法以及token的类型
  2. Payload(负载):用来存放实际需要传递的数据
  3. Signature(签名):服务器通过Payload、Header 和一个密钥(secret)使用Header里面指定的算法签名(默认是HMAC SHA256)生成

在基于 Token 进行身份验证的的应用程序中,服务器通过PayloadHeader和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端,客户端将 Token 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization字段中:Authorization: Bearer Token

2.3 JWT 工作流程

image-20191018002517227

  1. 用户向服务器发送用户名和密码用于登陆系统
  2. 身份验证服务响应并返回了签名的 JWT,上面包含了用户是谁的内容
  3. 用户以后每次想后端发请求都在Header中带上 JWT
  4. 服务端检查JWT 并从中获取用户相关信息

3. 什么是OAuth 2.0?

OAuth 是行业的标准授权协议,主要用来授权第三方应用获取有限的权限。

而 OAuth 2.0是对 OAuth 1.0 的完全重新设计,OAuth 2.0更快,更容易实现,OAuth 1.0 已经被废弃

实际上他就是一种授权机制,他的最终目的是为第三方应用颁发一个有时效性的令牌token。使得第三方应用能够通过该令牌获取相关资源

使用场景

  • 第三方登录:

    当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。

results matching ""

    No results matching ""