知方号

知方号

用户登录认证和权限授权(SpringSecurity、JWT、session)

用户登录认证和权限授权(SpringSecurity、JWT、session)

文章目录 前言一、登录认证1. 问题引入2. Session2.1 实现原理2.2 过滤器Filter2.3 上下文对象 3. JWT3.2 实现步骤3.3 拦截器 HandlerInterceptorAdapter3.4 上下文对象 4. Session VS JWT 二、权限授权1. 权限类型1.1 页面权限(菜单项权限)1.2 ACL模型 (Access Control List访问控制列表)不推荐1.3 RBAC模型(Role-Based Access Controller基于角色访问控制模型) 1.2 接口权限(操作权限或按钮权限)1.3 数据权限 三、SpringSecurity1. 概述2. 登录认证2.1 了解各个组件2.2 JWT+SpringSecurity 3. 权限授权 总结

前言

登录认证和权限授权是所有项目中必不可少的功能,本篇文章首先将通过最简单的方式(Session和JWT)实现登录认证和权限授权,然后再整合Springsecurity框架实现。

一、登录认证

登录认证简言之就是对用户的身份进行确认,判断用户的账号和密码是否正确。

1. 问题引入

HTTP请求是一个无状态的协议,每一次发送的请求都是独立的,需要一种机制来记住用户登录过? 需要凭证 怎么保存凭证? Session/JWT ,原理都是token机制

前端发起登录认证请求后端登录验证通过,返回给前端一个凭证前端发起新的请求时携带凭证 2. Session

有状态的管理机制 如果用户第一次访问某个服务器时,服务器响应数据时会在响应头的Set-Cookie标识里将Session Id返回给浏览器,浏览器就将标识中的数据存在Cookie中,浏览器后续访问服务器就会携带Cookie。

2.1 实现原理

2.2 过滤器Filter

问题引入:除了登录接口外,我们其他接口都要在Controller层里做登录判断,这太麻烦了。 解决:使用过滤器拦截,判断有没有登录,登录就放行,没登录结束请求

2.3 上下文对象

问题引入:要在service层获取操作用户对象,需要从Controller层传参过来太麻烦了。 解决:通过SpringMVC提供的RequestContextHolder对象在程序任何地方获取到当前请求对象,从而获取我们保存在HttpSession中的用户对象,写一个上下文对象来实现这一功能。 然后在Service层直接调用我们写的方法就可以获取到用户对象

3. JWT

Json web token。无状态管理机制

可以将一段数据加密成一段字符串,也可以从这字符串解密回数据可以对这个字符串进行校验,比如有没有过期,有没有被篡改 3.2 实现步骤

1、写一个JWT的工具类,工具类就提供两个方法一个生成一个解析 2、工具类做好之后我们可以开始写登录接口,登录的时候生成token 3、后续会话中,用户访问其他接口时就可以校验token来判断其是否已经登录。 一般来说,前端将token一般会放在请求头的Authorization项传递过来,其格式一般为类型 + token 调用其他接口的时候,从请求头中获取token,然后再通过JWT工具类解析token判断。

3.3 拦截器 HandlerInterceptorAdapter

如果每个接口都要手动判断一下用户有没有登录太麻烦了,所以我们做一个统一处理。 拦截器类写好之后,别忘了要使其生效,这里我们直接让SpringBoot启动类实现WebMvcConfigurer接 口,重写addInterceptors方法

3.4 上下文对象

在一个线程中横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context) JWT不像Session把用户信息直接存储起来,所以JWT的上下文对象要靠我们自己来实现。 这个类专门存储JWT解析出来的用户信息。我们要用到ThreadLocal存储用户信息,以防止线程冲突 通过上下文对象类(如UserContext),可以在程序的其他地方直接获取到数据。上下文对象.方法()

public final class UserContext { private static final ThreadLocal user = new ThreadLocal(); public static void add(String userName) { user.set(userName); } public static void remove() { user.remove(); } /** * @return 当前登录用户的用户名 */ public static String getCurrentUserName() { return user.get(); }} 4. Session VS JWT Session是有状态的,JWT是无状态的Session在服务端保存了用户信息,而JWT在服务端没有保存任何信息。当前端携带Session Id到服务端时,服务端要检查其对应的HttpSession中有没有保存用户信息,保存了就代表登录了当使用JWT时,服务端只需要对这个字符串进行校验,校验通过就代表登录了 二、权限授权

对用户能否问某个资源进行确认。认证成功之后,再确认能访问什么。 权限系统的设计,第一步就是考虑要保护什么资源,再接着思考如何保护这个资源。

1. 权限类型 1.1 页面权限(菜单项权限)

有权限的用户就会显示所有菜单,无权限的用户就只会显示部分菜单 一个页面(菜单)对应一个URI地址,当用户登录的时候判断这个用户拥有哪些页面权限,自然 而然就知道要渲染出什么导航菜单。

1.2 ACL模型 (Access Control List访问控制列表)不推荐

数据库设计三张表格,一张表用来存储用户信息,一张表存储资源路径,中间表用来映射用户和资源表的关系。 具体实现 前端给后端发请求后,后端回返回数据给前端,这些数据中就包含了用户能够访问的资源信息,前端本地也存有一个映射字典,字典里有资源的信息,比如id对应哪个路径、名称等等,前端拿到了用户的id后根据字典进行判断就可以做到相应的功能。

1.3 RBAC模型(Role-Based Access Controller基于角色访问控制模型)

很多用户的权限都是相同的,通过封装一层角色信息,实现角色和权限绑定,用户和角色绑定。

1.2 接口权限(操作权限或按钮权限)

前后端分离的模式下,后端在登录的时候将权限数据甩给前端后就再也不管了,如果此时用户的权限发生变化是无法通知前端的,并且数据存储在前端也容易被用户直接篡改,所以很不安全。 例如:没有这个删除权限的人就不会显示该按钮,或者该按钮被禁用. 页面渲染不走后端,但接口可必须得走后端,只需要对每个接口进行一个权限判断。 实现方式

接口扫描 RequestMappingInfoHandlerMapping,这个类可以拿到所有你

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。