首页 > 其他分享 >Spring Boot入坑-12-项目实战

Spring Boot入坑-12-项目实战

时间:2024-06-09 21:12:37浏览次数:28  
标签:12 加密 登录 Spring Boot 用户 信息 访问 Token

目标

  • 掌握后端项目整体架构搭建,掌握从0到1构建一个完整项目

  • 巩固已学习的后端技术,覆盖Java基础、Spring Boot的主要课程内容,包括但不限:序列化、反射、注解、泛型、Lambda、Stream、REST、Interceptor、数据访问、Swagger等等

  • 一些扩展内容的学习,比如登录、密码加密、项目部署等

需求

  • 一个测试人员记录开发Bug的Web前端网站

  • 核心功能:包含Bug列表、Bug信息维护,所有员工都能访问

  • 基础功能:人员信息维护、版本信息维护,供核心功能引用,仅管理员可以访问新增、修改、删除功能但所有员工能访问查询所有功能

  • 登录功能所有人都能访问

    项目需求图

【演示】

  1. 演示项目《BUG排行》项目,主要演示

    1. 未登录对接口访问返回401

    2. 不同角色用户登录,能访问不同接口

    3. 密码加密

开发步骤

一、数据库设计

  • 根据业务特点,设计数据表及表之间的关系

  • 实际的项目中,会有数据库设计的文档,使用Excel或PowerDesigner等工具进行

  • 设计好了数据表,将数据表创建到MySQL数据库中,提供数据服务

  • 项目只涉及3个表,分别是user、bug、version,具体见附件的bug_record_backend.sql脚本

  • 注意

    • 所有表的主键都为id,且为数据库自增

    • 所有表都有create_by_id、create_by_name、create_time、update_by_id、update_by_name、update_time

    数据库设计-物理模型图

【演示】

  1. 完成数据库的搭建与设计

二、搭建项目

  • 创建一个基于Web的Spring Boot项目

  • 按需要一次或逐步添加相应的包和类,主要的包,如下图

  • 这些包下的类的主要作用分别为

    • controller:控制器层,提供REST服务;很薄的一层,尽量不要有逻辑

    • service:服务层,承载了项目主要的业务功能,主要服务于控制器层

    • mapper:数据访问层,实现与数据库中的数据交互,使用MyBatis-Plus

    • entity:实体类包,里面的类与数据表一一对应,数据访问层中的Mapper都是针对entity进行操作,同时也在服务层被使用

    • dto:数据传输对象,用于控制器层、服务层对外提供请求/响应数据结构规范

    • config:通用配置包,所有的自定义配置类都定义在这个包,像Web配置、Swagger配置、数据库分页配置等

    • interceptor:拦截器包,包括对控制器层的REST服务权限拦截

    • annotation:注解包,包括是否需要进行权限拦截的注解

    • handler:操作包,包含实体类拦截类

    • util:工具包,封装了常用的工具,像密码加密、会话工具

【演示】

  1. 完成包层次定义

三、添加基本功能

  • 添加如下基本功能,包括pom.xml依赖config包下配置类application.properties中的配置节

    • Swagger

    • Lombok

    • 对象映射

    • 标准响应封装,见dto.common.ResponseData类

    • 通用异常处理,见advice.GlobalExceptionHandler类

    • 通用验证框架,见advice.GlobalExceptionHandler类

    • 会话工具类,见util.SessionUtil类

    • 密码加密工具类,见util.PasswordUtil类

  • 并添加一个控制器,测试能提供基本的REST服务

【演示】

  1. 完成基本功能添加、控制器输出、会话工具类定义、密码加密工具类定义

四、集成数据访问

  • 数据访问是一个软件项目的核心

  • 项目中使用MyBatis-Plus,按顺序通过下列步骤进行集成

    1. 添加依赖,数据库产品依赖和MyBatis-Plus依赖

    2. 添加配置,在application.properties中添加数据库配置

    3. 添加分页组件,见config.MyBatisPlusConfig类

    4. 添加实体类,用于与数据表一一对应,见entity包下的类

    5. 添加Mapper,见mapper包下的接口

    6. 添加Service,并继承MyBatis-Pluse中的服务接口和类,见service包下的接口、service\impl包下的类

    7. 添加用户信息CRUD,一切的数据都由用户产生,很多独立的系统都由构建用户信息开始,注意使用DTO和ResponseData

    8. 添加创建、修改信息拦截,见handler.CommonMetaObjectHandler类,里面使用了会话工具类

  • 注意,部分数据需要进行手动数据类型转换,如对于数据库中使用逗号分隔的内容,在程序中可以处理成List<String>;如用户表中的roles字段中的admin,staff,可转换成List<String>,包含两个元素,具体是通过TypeHandler接口实现,步骤如下

    1. 实现TypeHandler接口,主要实现其中的Java类型转DB类型、DB类型转Java类型,见entity.ListTypeHandler类

    2. 应用到实体类,对需要进行此种转换的实体类

      1. 在类上,@TableName注解中添加属性autoResultMap = true

      2. 在属性上,@TableFiled注解中进行应用,格式为 @TableField(jdbcType = JdbcType.VARCHAR,typeHandler = ListTypeHandler.class)

【演示】

  1. 完成用户各层次CRUD,注意其中的通用性验证、业务性验证、请求信息拦截、类型转换

五、集成登录

  • 大部分的软件,都需要登录后,才能访问,后端的REST服务也是如此

  • 具体的过程

    1. 添加登录控制器和功能,见controller.AccountController类、service.impl.AccountService类

    2. 将登录信息保存到会话(HttpSession),参考util.SessionUtil工具

    3. 应用到业务,创建、修改信息拦截

  • 另外,再考虑注册登出接口

【演示】

  1. 完成集成登录,使用明文密码

六、密码加密

  • 项目中一定不能将明文密码保存到数据库,必须加密后再存储

  • 一般会定义一个密码加密工具,对密码进行加密,且密码不能解密,并加盐防止彩虹表破解

  • 密码加密主要在代码中下面部分使用

    • 新增用户,密码需要加密保存

    • 注册

    • 修改密码

    • 登录,都使用加密后的密码进行比较

【演示】

  1. 完成集成密码加密

七、认证与授权--基于Session

认证与授权时序图
  • 如上图一般,除了登录、注册服务,其他服务都需要登录才能使用

  • 不同用户登录后,访问的REST服务也不一样,一般根据其角色决定,不同的用户使用不同的服务

  • 如何完成按角色过滤REST服务访问权限?具体实现步骤如下

    1. 设计权限过滤注解,自定义注解@UserRight,里面包含roles属性,用于标识使用该注解的类或方法需要根据角色进行权限过滤;就此项目业务,见annotaion.UserRight注解

      1. staff角色,所有人员都可访问,Bug信息所有接口、人员信息的查询所有接口、版本信息的查询所有接口

      2. admin角色,仅管理员访问,人员信息除了查询所有之外接口、版本信息除了查询所有之外接口

    2. 设计登录接口,请求参数为用户名和密码,登录成功,将用户信息存入HttpSession,这个前面已经完成,见controller.AccountController类

    3. 设计拦截器,对自定义注解@UserRight进行拦截,根据注解中需要的角色与登录时保存在HtppSession中用户拥有的角色进行比对,如果当前用户拥有访问接口需要的角色权限,可以访问;否则,拒绝访问,具体如下;见interceptor.AuthenticationInterceptor类

      • 无需权限访问,像账户控制器中的访问,主要用于登录

      • 登录才能访问,其他的所有控制器的访问

      • 登录且具备权限才能访问,基础数据中的CRUD方法(除了queryAll)之外

    4. 绑定拦截器,将拦截器绑定到/**的路由中,拦截所有的Action,见config.WebConfig类

    5. 标注REST服务,对需要进行权限过滤的REST服务,添加注解@UserRight注解,并配置角色,见controller.UserController类、controller.VersionController类、controller.BugController类

    6. 查看拦截效果,通过未登录、staff登录用户、admin登录用户查看不同效果

【演示】

  1. 完成认证与授权

八、业务功能开发

  • 上述功能完成后,一个基本的软件框架就搭建好了

  • 后续根据业务,往各个层次添加代码即可,主要有

    • 版本业务

    • BUG业务

    • ...

【演示】

  1. 完成业务功能开发

九、与前端集成

  • 学完前端后可实现

十、打包与发布

  • 项目开发完成后,打包并部署到Linux服务器,具体参考打包和发布

【演示】

  1. 完成项目打包并部署到CentOS 7服务器,具体参考打包和发布

【练习】

  1. 完成演示代码编写

实战和作业

  1. 完成项目实战,具体代码见bug-record-backend

补充-1:认证与授权--基于Token

传统Token

  • 传统的Token,是在服务器生成,并保存相应的信息在服务器(如Redis),然后返回给用户保存

JWT(JSON Web Token)

  • 数据不再保留在服务器,而是由客户端保存自己登录后获取的Token

  • 后续对服务器的请求,都需要携带Token

  • 服务器对Token中的信息进行解密后,识别当前用户信息,是否过期等数据,进行认证与授权

  • JWT中的内容分为Header、Payload、Signature三部分

    • Header:存放类型、加密算法

    • Payload:存储超时时间、用户自定义信息等

    • Signature:经过密钥签名的加密信息,安全的保证

  • 使用Base64进行编码

特点

  • 一般无需服务器端通过会话或缓存保存信息

  • 无需cookies支持

与Session对比

相同点
  • 作用相同,都是在HTTP协议无状态特性下,用于记住多次请求时的用户票据相关信息,实现认证与授权

不同点
  • 保存方式

    • Session,使用内存或缓存保存用户票据信息,并通过Cookies形式下发Session ID到客户端浏览器;客户端浏览器每次请求都通过Cookies携带这个Session ID,来告诉服务器“我是谁”

    • Token,通过自包含形式保存用户票据信息,服务器端无需存储相关信息;客户端每次请求一般都通过请求头Header携带这个Token

  • 过期时间

    • Session,服务器端Session和下发到Cookies的Session ID都可以设置过期时间

    • Token,过期时间也是通过自包含形式保存,一般服务器不可以过期掉Token

  • 加密方式

    • Session,由于用户票据信息保存在服务器端,无需加密,只下发唯一的Session ID给客户端即可

    • Token,使用密钥配合加密算法加密,只要密钥不泄露,相对安全

  • 多负载

    • Session,要处理分布式会话共享

    • Token,只要密钥、加密算法一致,单体与多负载处理方法也一致,适合微服务

使用方式

  • 使用方式与会话模式一致,查看附件项目中有标识【JWT】的内容部分

    1. 引入依赖

      <!--【JWT】1、引入依赖-->
      <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>3.18.3</version>
      </dependency>
    2. 设计加密工具类,确定密钥、过期时间等;具体见附件项目中的util.JWTUtil类

    3. 登录时返回Token,使用工具类,生成token并返回给请求方;见附件项目中的dto.output.account.LoignOutputDto类、service.impl.AccountServiceImpl类;并可在https://jwt.io查看jwt内容

    4. 拦截器中使用Token进行认证与授权,验证token的有效性,并根据里面的Payload信息进行授权验证;见附件项目中的interceptor.AuthenticationInterceptor类

    5. 自动填充中表和Token中的用户信息,使用token信息,如果像创建人、更新人自动填充中使用第4步的方式获取token中的Payload信息进行填充

【演示】

  1. 基于Token的认证与授权,见附件中项目bug-record-backend-token

补充-2:认证与授权--基于Spring Security【了解】

概述

  • Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案

  • 一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)

    • 用户认证

      • 是验证某个用户是否为系统中的合法主体,即用户能否访问该系统

      • 一般要求用户提供用户名和密码

      • 系统通过校验用户名和密码来完成认证过程

    • 用户授权

      • 是验证某个用户是否有权限执行某个操作

      • 在软件中,不同用户所具有的权限是不同的;比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改

      • 系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限

  • 一般会对接基于角色的访问控制(RBAC,Role-Based Access Control )

使用方式

  • 使用方式与会话模式一致,查看附件项目中有标识【JWT】的内容部分

    1. 引入依赖

      <!--【SpringSecurity】1、引入依赖-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
    2. 定义UserDetails子类

      1. 将一些验证项返回true

      2. 包含用户信息(UserEntity类型)的属性

      3. 使用用户信息中的角色转换成Spring Security中的角色

      4. 见附件项目中的security.UserDetailsImpl类

    3. 定义UserDetailsService子类

      1. 覆盖loadUserByUsername方法,在此方法中,会接收到用户名,根据用户名从数据库中获取用户信息(UserEntity对象)

      2. 并返回上一步的UserDetails子类对象,里面包含从数据库中查询到的用户信息对象

      3. 见附件项目中的security.UserDetailsServiceImpl类

    4. 注入加密工具BCryptPasswordEncoder

      1. 定义BCryptPasswordEncoder工具类对象,并注入到Spring容器,采用SHA-256 +随机盐+密钥对密码进行加密

      2. 见附件项目中的security.WebSecurityConfig类中的passwordEncoder方法

    5. 注入按角色进行授权类SecurityFilterChain

      1. 使用HttpSecurity类对象,进行URL与角色匹配,完成Action认证与授权逻辑

      2. 见附件项目中的security.WebSecurityConfig类中的securityFilterChain方法,且类上需要加上@EnableWebSecurity注解

    6. 使用加密工具BCryptPasswordEncoder,分别在下列逻辑中使用

      1. 注册

      2. 新增用户

      3. 重置密码

    7. 获取登录用户信息,使用下列代码获取,一般用于创建信息、更新信息拦截中

      //从SpringSecurity获取用户信息
      Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
      //登录票据
      UserDetailsImpl userDetails = null;
      if(authentication.getPrincipal() instanceof UserDetailsImpl) {
          userDetails = (UserDetailsImpl) authentication.getPrincipal();
      }
    8. 认证与授权就生效了

【演示】

  1. 基于Spring Security的认证与授权,见附件中项目bug-record-backend-spring-security

代码

网盘地址:链接:https://pan.baidu.com/s/1bCIsfG390nh-mTLzkAi7Bw?pwd=8888 

标签:12,加密,登录,Spring,Boot,用户,信息,访问,Token
From: https://www.cnblogs.com/sangrei/p/18240010

相关文章

  • Spring Boot入坑-10-Git
    简介一个开源的分布式版本控制系统基于Git协议的代码托管平台主要有Github和Gitlab,国内的也有比如Gitee比较多的企业使用Gitlab构建自己的代码托管平台其主要作用是,对代码或文档进行版本化记录与控制主要概念工作区:个人电脑中能看到的项目的目录暂存区:数据暂......
  • 基于springboot+vue.js+uniapp小程序的流浪猫狗救助救援网站附带文章源码部署视频讲解
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaits系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • SpringBoot实现上传头像(查看头像)
    SpringBoot实现上传头像给功能和查看头像功能文章目录目录文章目录1.上传头像1.这里的AppConfig记得定义一下 2.引入AppConfig3.上传文件代码 2.获取头像 1.实现readFile方法1.上传头像首先我的代码中在application.properties中设置了上传文件的根目录......
  • SpringBoot社区配送服务系统小程序-计算机毕业设计源码88705
    摘要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,社区当然也不例外。社区配送服务系统小程序是以实际运用为开发背景,运用软件工程原理和开发方法,采用Java技术构建的一个管理系统。整个开发过程首先对软件系统进......
  • SpringCloud-OpenFeign拓展-连接池、最佳使用方法、日志输出
    目录1OpenFeign连接池1.1常见连接类型1.2连接池使用方法1.2.1引入依赖1.2.2开启连接池功能1.2.3配置完成,重启实例即可,底层将更改设置。2OpenFeign最佳使用方法2.1每个微服务都是单独的project,内部有三个独立模块2.2每个微服务都是一个module,一个project,内设......
  • springboot+vue在线考试系统附带文章和源代码部署讲解等
    文章目录前言项目运行效果截图技术栈后端springboot框架:后端mybatis框架:前端框架vue:数据库mysql:开发环境代码参考数据库参考源码质量保障源码获取前言......
  • springboot+vue养老院管理系统附带文章和源代码部署讲解等
    文章目录前言项目运行效果截图技术栈后端springboot框架:后端mybatis框架:前端框架vue:数据库mysql:开发环境代码参考数据库参考源码质量保障源码获取前言......
  • springboot+vue医院管理系统附带文章和源代码部署讲解等
    文章目录前言项目运行效果截图技术栈后端springboot框架:后端mybatis框架:前端框架vue:数据库mysql:开发环境代码参考数据库参考源码质量保障源码获取前言......
  • jquery 封装 bootstrap table
    简易代码如下:JS如下:$.fn.extend({table:function(opts){consttableConfig={mode:'debug'}consttablePreset={limit:10,}//TheinstanceconstTable={......
  • SpringBoot3集成Knife4j生成接口文档
    导入依赖<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.4.0</version></dependency>注意:SpringBoot......