Java项目实战《苍穹外卖》 三、登录功能

测测你是什么人格吧,地址: MBTI 16种人格测试官网

在这里插入图片描述


系列文章目录

苍穹外卖是黑马程序员2023年的Java实战项目,作为业余练手用,需要源码或者课程的可以找我,无偿分享


  1. Java项目实战《苍穹外卖》 一、项目概述
  2. Java项目实战《苍穹外卖》 二、项目搭建
  3. Java项目实战《苍穹外卖》 三、登录功能

文章目录

    • 系列文章目录
    • 一、功能实现
      • 1.1 实现思路
      • 1.2 数据库连接
      • 1.3 Service层
      • 1.4 ServiceImpl层
      • 1.5 Controller层
      • 1.6 Mapper层
      • 1.7 Postman
    • 二、nginx
      • 2.1 思考
      • 2.2 反向代理
        • 2.2.1 nginx 反向代理的好处
        • 2.2.2 nginx 反向代理的配置方式
      • 2.3 负载均衡
        • 2.3.1 nginx 负载均衡的配置方式
        • 2.3.2 nginx 负载均衡策略
    • 三、会话跟踪方案
      • 3.1 什么是会话技术
      • 3.2 Cookie
        • 3.2.1 会话跟踪技术
        • 3.2.2 为什么这一切都是自动化进行的
        • 3.2.3 优缺点
      • 3.3 Session
        • 3.3.1 会话跟踪技术
        • 3.3.2 优缺点
      • 3.4 令牌技术
    • 四、JWT令牌
      • 4.1 介绍
      • 4.2 JWT令牌的生成
        • 4.2.1 引入JWT的依赖
        • 4.2.2 测试类
        • 4.2.3 执行结果
      • 4.3 校验JWT令牌
        • 4.3.1 测试类
        • 4.3.2 执行结果
        • 4.3.3 方案二:官网校验
    • 五、完善登录功能
      • 5.1 接口描述
      • 5.2 JWT工具类
      • 5.3 Controller
      • 5.4 拦截器
    • 六、密码加密
      • 6.1 问题
      • 6.2 解决思路
      • 6.3 实现步骤
        • 6.3.1 使用SQLyog获取MD5加密
        • 6.3.2 修改数据库中明文密码
        • 6.3.3 完善登录功能
        • 6.3.4 Postman测试



一、功能实现

1.1 实现思路

在这里插入图片描述

1.2 数据库连接

编辑 sky-server/src/main/resources/application-dev.yml 文件:

sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: sky_take_outusername: root # 本地数据库账号password: root # 本地数据库密码

1.3 Service层

编辑 sky-server/src/main/java/com/sky/service/EmployeeService.java 文件:

public interface EmployeeService {/*** 员工登录* @param employeeLoginDTO* @return*/Employee login(EmployeeLoginDTO employeeLoginDTO);}

1.4 ServiceImpl层

编辑 sky-server/src/main/java/com/sky/service/impl/EmployeeServiceImpl.java 文件:

/*** 登录** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("员工登录:{}", employeeLoginDTO);//调用service方法查询数据库Employee employee = employeeService.login(employeeLoginDTO);//登录成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, employee.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);}

1.5 Controller层

编辑 sky-server/src/main/resources/application-dev.yml 文件:

/*** 员工登录** @param employeeLoginDTO* @return*/public Employee login(EmployeeLoginDTO employeeLoginDTO) {String username = employeeLoginDTO.getUsername();String password = employeeLoginDTO.getPassword();//1、根据用户名查询数据库中的数据Employee employee = employeeMapper.getByUsername(username);//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)if (employee == null) {//账号不存在throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对if (!password.equals(employee.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}if (employee.getStatus() == StatusConstant.DISABLE) {//账号被锁定throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象return employee;}

1.6 Mapper层

编辑 sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java 文件:

@Mapper
public interface EmployeeMapper {/*** 根据用户名查询员工* @param username* @return*/@Select("select * from employee where username = #{username}")Employee getByUsername(String username);}

1.7 Postman

在这里插入图片描述



二、nginx

2.1 思考

对登录功能测试完毕后,接下来,我们思考一个问题:前端发送的请求,是如何请求到后端服务的?
在这里插入图片描述


2.2 反向代理

nginx 反向代理,就是将前端发送的动态请求由 nginx 转发到后端服务器
在这里插入图片描述

2.2.1 nginx 反向代理的好处
  • 提高访问速度

    因为nginx本身可以进行缓存,如果访问的同一接口,并且做了数据缓存,nginx就直接可把数据返回,不需要真正地访问服务端,从而提高访问速度。

  • 进行负载均衡

    所谓负载均衡,就是把大量的请求按照我们指定的方式均衡的分配给集群中的每台服务器。

  • 保证后端服务安全

    因为一般后台服务地址不会暴露,所以使用浏览器不能直接访问,可以把nginx作为请求访问的入口,请求到达nginx后转发到具体的服务中,从而保证后端服务的安全。

2.2.2 nginx 反向代理的配置方式
server{listen 80;server_name localhost;location /api/{proxy_pass http://localhost:8080/admin/; #反向代理}
}

proxy_pass: 该指令是用来设置代理服务器的地址,可以是主机名称,IP地址加端口号等形式。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../.. 这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://localhost:8080/admin/ 上来。


2.3 负载均衡

当如果服务以集群的方式进行部署时,那nginx在转发请求到服务器时就需要做相应的负载均衡。其实,负载均衡从本质上来说也是基于反向代理来实现的,最终都是转发请求。

2.3.1 nginx 负载均衡的配置方式
upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;
}
server{listen 80;server_name localhost;location /api/{proxy_pass http://webservers/admin;#负载均衡}
}

upstream: 如果代理服务器是一组服务器的话,我们可以使用upstream指令配置后端服务器组。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../.. 这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://webservers/admin,根据webservers名称找到一组服务器,根据设置的负载均衡策略(默认是轮询)转发到具体的服务器。

注: upstream后面的名称可自定义,但要上下保持一致。


2.3.2 nginx 负载均衡策略
名称说明
轮询默认方式
weight权重方式,默认为1,权重越高,被分配的客户端请求就越多
ip_hash依据ip分配方式,这样每个访客可以固定访问一个后端服务
least_conn依据最少连接方式,把请求优先分配给连接数少的后端服务
url_hash依据url分配方式,这样相同的url会被分配到同一个后端服务
fair依据响应时间方式,响应时间短的服务将会被优先分配
  • 轮询

    upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;
    }
    
  • weight

    upstream webservers{server 192.168.100.128:8080 weight=90;server 192.168.100.129:8080 weight=10;
    }
    
  • ip_hash

    upstream webservers{ip_hash;server 192.168.100.128:8080;server 192.168.100.129:8080;
    }
    
  • least_conn

    upstream webservers{least_conn;server 192.168.100.128:8080;server 192.168.100.129:8080;
    }
    
  • url_hash

    upstream webservers{hash &request_uri;server 192.168.100.128:8080;server 192.168.100.129:8080;
    }
    
  • fair

    upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;fair;
    }
    


三、会话跟踪方案

3.1 什么是会话技术

  • 在我们日常生活当中,会话指的就是谈话、交谈。

  • 在web开发当中,会话指的就是浏览器与服务器之间的一次连接,我们就称为一次会话。

会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

服务器会接收很多的请求,但是服务器是需要识别出这些请求是不是同一个浏览器发出来的。比如:1和2这两个请求是不是同一个浏览器发出来的,3和5这两个请求不是同一个浏览器发出来的。如果是同一个浏览器发出来的,就说明是同一个会话。如果是不同的浏览器发出来的,就说明是不同的会话。而识别多次请求是否来自于同一浏览器的过程,我们就称为会话跟踪。

我们使用会话跟踪技术就是要完成在同一个会话中,多个请求之间进行共享数据。

为什么要共享数据呢?

由于HTTP是无状态协议,在后面请求中怎么拿到前一次请求生成的数据呢?此时就需要在一次会话的多次请求之间进行数据共享

3.2 Cookie

3.2.1 会话跟踪技术

cookie 是客户端会话跟踪技术,它是存储在客户端浏览器的,我们使用 cookie 来跟踪会话,我们就可以在浏览器第一次发起请求来请求服务器的时候,我们在服务器端来设置一个cookie。

比如第一次请求了登录接口,登录接口执行完成之后,我们就可以设置一个cookie,在 cookie 当中我们就可以来存储用户相关的一些数据信息。比如我可以在 cookie 当中来存储当前登录用户的用户名,用户的ID。

服务器端在给客户端在响应数据的时候,会自动的将 cookie 响应给浏览器,浏览器接收到响应回来的 cookie 之后,会自动的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中,都会将浏览器本地所存储的 cookie 自动地携带到服务端。
在这里插入图片描述

3.2.2 为什么这一切都是自动化进行的

是因为 cookie 它是 HTP 协议当中所支持的技术,而各大浏览器厂商都支持了这一标准。在 HTTP 协议官方给我们提供了一个响应头和请求头:

  • 响应头 Set-Cookie :设置Cookie数据的
  • 请求头 Cookie:携带Cookie数据的

在这里插入图片描述

3.2.3 优缺点
  • 优点: HTTP协议中支持的技术(像Set-Cookie 响应头的解析以及 Cookie 请求头数据的携带,都是浏览器自动进行的,是无需我们手动操作的)

  • 缺点:

    • 移动端APP(Android、IOS)中无法使用Cookie
    • 不安全,用户可以自己禁用Cookie
    • Cookie不能跨域

3.3 Session

Session是服务器端会话跟踪技术,所以它是存储在服务器端的。而 Session 的底层其实就是基于 Cookie 来实现的。

3.3.1 会话跟踪技术
  • 获取Session
    在这里插入图片描述

    如果我们现在要基于 Session 来进行会话跟踪,浏览器在第一次请求服务器的时候,我们就可以直接在服务器当中来获取到会话对象Session。如果是第一次请求Session ,会话对象是不存在的,这个时候服务器会自动的创建一个会话对象Session 。而每一个会话对象Session ,它都有一个ID(示意图中Session后面括号中的1,就表示ID),我们称之为 Session 的ID。

  • 响应Cookie (JSESSIONID)
    在这里插入图片描述
    接下来,服务器端在给浏览器响应数据的时候,它会将 Session 的 ID 通过 Cookie 响应给浏览器。其实在响应头当中增加了一个 Set-Cookie 响应头。这个 Set-Cookie 响应头对应的值是不是cookie? cookie 的名字是固定的 JSESSIONID 代表的服务器端会话对象 Session 的 ID。浏览器会自动识别这个响应头,然后自动将Cookie存储在浏览器本地。

  • 查找Session
    在这里插入图片描述
    接下来,在后续的每一次请求当中,都会将 Cookie 的数据获取出来,并且携带到服务端。接下来服务器拿到JSESSIONID这个 Cookie 的值,也就是 Session 的ID。拿到 ID 之后,就会从众多的 Session 当中来找到当前请求对应的会话对象Session。


3.3.2 优缺点
  • 优点: Session是存储在服务端的,安全
  • 缺点:
    • 服务器集群环境下无法直接使用Session
    • 移动端APP(Android、IOS)中无法使用Cookie
    • 用户可以自己禁用Cookie
    • Cookie不能跨域

PS:Session 底层是基于Cookie实现的会话跟踪,如果Cookie不可用,则该方案,也就失效了。


3.4 令牌技术

如果通过令牌技术来跟踪会话,我们就可以在浏览器发起请求。在请求登录接口的时候,如果登录成功,就可以生成一个令牌,令牌就是用户的合法身份凭证。接下来我在响应数据的时候,就可以直接将令牌响应给前端

接下来我们在前端程序当中接收到令牌之后,就需要将这个令牌存储起来。这个存储可以存储在 cookie 当中,也可以存储在其他的存储空间(比如:localStorage)当中。

接下来,在后续的每一次请求当中,都需要将令牌携带到服务端。携带到服务端之后,接下来我们就需要来校验令牌的有效性。如果令牌是有效的,就说明用户已经执行了登录操作,如果令牌是无效的,就说明用户之前并未执行登录操作。

此时,如果是在同一次会话的多次请求之间,我们想共享数据,我们就可以将共享的数据存储在令牌当中就可以了。

在这里插入图片描述
优缺点

  • 优点:
    • 支持PC端、移动端
    • 解决集群环境下的认证问题
    • 减轻服务器的存储压力(无需在服务器端存储)
  • 缺点: 需要自己实现(包括令牌的生成、令牌的传递、令牌的校验)

针对于这三种方案,现在企业开发当中使用的最多的就是第三种令牌技术进行会话跟踪。而前面的这两种传统的方案,现在企业项目开发当中已经很少使用了。所以在我们的课程当中,我们也将会采用令牌技术来解决案例项目当中的会话跟踪问题。



四、JWT令牌

4.1 介绍

JWT全称: JSON Web Token (官网:https://jwt.io/)

  • 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

    简洁:是指jwt就是一个简单的字符串。可以在请求参数或者是请求头当中直接传递。

    自包含:指的是jwt令牌,看似是一个随机的字符串,但是我们是可以根据自身的需求在jwt令牌中存储自定义的数据内容。如:可以直接在jwt令牌中存储用户的相关信息。

    简单来讲,jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在通信双方安全的进行信息传输了。

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)

  • Header(头):, 记录令牌类型、签名算法等。 例如:{“alg”:“HS256”,“type”:“JWT”}

  • Payload(有效载荷):,携带一些自定义信息、默认信息等。 例如:{“id”:“1”,“username”:“Tom”}

  • Signature(签名):,防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。

    签名的目的就是为了防jwt令牌被篡改,而正是因为jwt令牌最后一个部分数字签名的存在,所以整个jwt 令牌是非常安全可靠的。一旦jwt令牌当中任何一个部分、任何一个字符被篡改了,整个令牌在校验的时候都会失败,所以它是非常安全可靠的。

在这里插入图片描述

JWT令牌最典型的应用场景就是登录认证:

  1. 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。
  2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。
  3. 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

4.2 JWT令牌的生成

4.2.1 引入JWT的依赖
<!-- JWT依赖-->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
4.2.2 测试类

新建 sky-server/src/test/java/JwtTest.java 文件:

public class JwtTest {/*** 生成令牌*/@Testpublic void getJwt() {HashMap<String, Object> claims = new HashMap<>();claims.put("username", "tom");claims.put("password", "123456");String jwt = Jwts.builder().setClaims(claims) //自定义内容(载荷).signWith(SignatureAlgorithm.HS256,"better") //签名算法.setExpiration(new Date(System.currentTimeMillis() + 60*1000)) //有效期60秒.compact();System.out.println("jwt -> " + jwt);// jwt -> eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsImV4cCI6MTcwMDU2NTY5NywidXNlcm5hbWUiOiJ0b20ifQ.E0RTUaT5CoEod4NTgKoVMnH0BRdP2cOORKyw8KXMicM}
}
4.2.3 执行结果

在这里插入图片描述

4.3 校验JWT令牌

4.3.1 测试类

编辑 sky-server/src/test/java/JwtTest.java 文件:

public class JwtTest {.../*** 令牌解析*/@Testpublic void parserJwt() {Claims claims = Jwts.parser().setSigningKey("better")//指定签名密钥(必须保证和生成令牌时使用相同的签名密钥).parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsImV4cCI6MTcwMDU2NTg0MiwidXNlcm5hbWUiOiJ0b20ifQ.OJUWynySGYBT1b0BSKBKb2i0k0Gms5C33sd6pp_3jxg").getBody();System.out.println("令牌解析: " + claims);// 令牌解析: {password=123456, exp=1700565842, username=tom}}
}
4.3.2 执行结果

在这里插入图片描述

4.3.3 方案二:官网校验

在这里插入图片描述



五、完善登录功能

5.1 接口描述

WT令牌怎么返回给前端呢?就需要再来看一下接口文档当中关于登录接口的描述:

响应数据:

参数格式:application/json

参数说明:

名称类型是否必须默认值备注其他信息
codenumber必须响应码, 1 成功 ; 0 失败
msgstring非必须提示信息
datastring必须返回的数据 , jwt令牌

响应数据样例:

{"code": 1,"msg": "success","data": "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"
}

5.2 JWT工具类

查看 sky-common/src/main/java/com/sky/utils/JwtUtil.java 文件:

public class JwtUtil {/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥** @param secretKey jwt秘钥* @param ttlMillis jwt过期时间(毫秒)* @param claims    设置的信息* @return*/public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT的时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** Token解密** @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param token     加密后的token* @return*/public static Claims parseJWT(String secretKey, String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}}

5.3 Controller

查看 sky-server/src/main/java/com/sky/controller/admin/EmployeeController.java 文件:

/*** 员工管理*/
@RestController
@RequestMapping("/admin/employee")
@Slf4j //这是lombok的输出日志注解,这个日志信息更加完整,包含类的完整名,日志打印的时间
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@Autowiredprivate JwtProperties jwtProperties;/*** 登录** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO, HttpSession session) {log.info("员工登录:{}", employeeLoginDTO);Employee employee = employeeService.login(employeeLoginDTO);//将登录数据员工id存储到session会话中session.setAttribute("employee",employee.getId());//生成令牌Map<String, Object> claims = new HashMap<>();//将员工的id写入载荷claims.put(JwtClaimsConstant.EMP_ID,employee.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);//由于EmployeeLoginVO 使用@Builder注解就可以使用链式构建对象EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);}/*** 退出** @return*/@PostMapping("/logout")public Result<String> logout() {return Result.success();}}

5.4 拦截器

查看 sky-server/src/main/java/com/sky/interceptor/JwtTokenAdminInterceptor.java 文件:

/*** jwt令牌校验的拦截器*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("当前员工id:", empId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}


六、密码加密

6.1 问题

员工表中的密码是明文存储,安全性太低。
在这里插入图片描述

6.2 解决思路

  1. 将密码加密后存储,提高安全性
    在这里插入图片描述
  2. 使用MD5加密方式对明文密码加密
    在这里插入图片描述

6.3 实现步骤

6.3.1 使用SQLyog获取MD5加密

在这里插入图片描述

6.3.2 修改数据库中明文密码

在这里插入图片描述

6.3.3 完善登录功能

编辑 sky-server/src/main/java/com/sky/service/impl/EmployeeServiceImpl.java 文件:

@Service
public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeMapper employeeMapper;/*** 员工登录** @param employeeLoginDTO* @return*/public Employee login(EmployeeLoginDTO employeeLoginDTO) {String username = employeeLoginDTO.getUsername();String password = employeeLoginDTO.getPassword();//1、根据用户名查询数据库中的数据Employee employee = employeeMapper.getByUsername(username);//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)if (employee == null) {//账号不存在throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对// TODO 后期需要进行md5加密,然后再进行比对//对用户输入的明文密码加密password = DigestUtils.md5DigestAsHex(password.getBytes());if (!password.equals(employee.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}if (employee.getStatus() == StatusConstant.DISABLE) {//账号被锁定throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象return employee;}}
6.3.4 Postman测试

在这里插入图片描述



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/201232.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10月起个税系统升级,3个月个税零申报将收到提示

近日&#xff0c;自然人电子税务局扣缴端升级了&#xff0c;升级后对于工资薪金收入连续三个月为零的纳税人&#xff0c;系统会自动出现以下提示。这个提示主要为了避免企业长期对已经离职的员工进行零申报&#xff0c;导致数据不准确和资源浪费。HR在申报个税时&#xff0c;一…

虚拟摇杆OnJoystickMove未被调用,角色不移动

更改interaction type 为 event notification

什么是应急演练脚本?其设计原则是什么?

应急演练脚本是一种系统性、有计划的模拟性文件&#xff0c;旨在测试和评估组织在紧急情况下的应对能力。这种脚本提供了一系列步骤和场景&#xff0c;以确保团队能够高效、协调地应对各种紧急事件。以下将详细探讨应急演练脚本的定义、设计原则以及实施过程。 一、应急演练脚本…

React整理总结(五、Redux)

1.Redux核心概念 纯函数 确定的输入&#xff0c;一定会产生确定的输出&#xff1b;函数在执行过程中&#xff0c;不能产生副作用 store 存储数据 action 更改数据 reducer 连接store和action的纯函数 将传入的state和action结合&#xff0c;生成一个新的state dispatc…

IPFoxy:什么是数据中心代理IP?好用吗?

数据中心代理是代理IP中最常见的类型&#xff0c;也被称为机房IP。这些代理服务器为用户分配不属于 ISP&#xff08;互联网服务提供商&#xff09;而来自第三方云服务提供商的 IP 地址。数据中心代理的最大优势——它们允许在访问网络时完全匿名。 如果你正在寻找海外代理IP&am…

【Java 进阶篇】揭秘 Jackson:Java 对象转 JSON 注解的魔法

嗨&#xff0c;亲爱的同学们&#xff01;欢迎来到这篇关于 Jackson JSON 解析器中 Java 对象转 JSON 注解的详细解析指南。JSON&#xff08;JavaScript Object Notation&#xff09;是一种常用于数据交换的轻量级数据格式&#xff0c;而 Jackson 作为一款优秀的 JSON 解析库&am…

js进阶笔记之原型,原型链

目录 1、原型对象 constructor 属性 对象原型 2、原型链 3、instanceof 4、原型继承 1、原型对象 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候再一个一个的依次调用就可以了。 面向对象是把事务分解成为…

python刷题笔记1(42例题)

1. split()函数 str.split([sep [, maxsplit]]) 分割字符串&#xff0c;返回一个数组 2. 判断子串 # 判断子串是否在主串里面&#xff0c;是则输出“Yes”&#xff0c;否则输出“No” str1 input("子串&#xff1a;") str2 input("主串:") if str1 in s…

最新绿豆APP源码苹果CMS影视插件版本/原生JAVA源码+反编译开源+免授权

源码简介&#xff1a; 最新绿豆APP源码苹果CMS影视插件版本&#xff0c;它是原生JAVA源码反编译开源免授权&#xff0c;绿豆影视对接苹果CMS&#xff0c;它可以支持多功能自定义DIY页面布局。 1、新版绿豆视频APP视频6.1插件版反编译指南及教程 2、后端插件开源&#xff0c;可…

创建 Springboot 项目

前言 创建 Spring Boot 项目是很多Java开发人员入门的重要一步&#xff01; 欢迎来到本篇关于创建 Spring Boot 项目的博客&#xff01;Spring Boot作为一个快速、便捷的开发框架&#xff0c;为我们提供了简化和加速应用程序开发的利器。 在这个数字化时代&#xff0c;快速响…

在Jupyter Lab中使用多个环境,及魔法命令简介

一、Jupyter Lab使用conda虚拟环境 1、给虚拟环境添加 ipykernel 方法一: 创建环境时直接添加ipykernel 方法&#xff1a;conda create -n 【虚拟环境名称】python3.8 ipykernel实例如下&#xff1a; conda create -n tensorflow_cpu python3.8 ipykernel 方法二&#xff…

解决Vision Transformer在任意尺寸图像上微调的问题:使用timm库

解决Vision Transformer在任意尺寸图像上微调的问题&#xff1a;使用timm库 文章目录 一、ViT的微调问题的本质二、Positional Embedding如何处理1&#xff0c;绝对位置编码2&#xff0c;相对位置编码3&#xff0c;对位置编码进行插值 三、Patch Embedding Layer如何处理四、使…

【0到1学习Unity脚本编程】第一人称视角的角色控制器

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;【0…

7.Gin 路由详解 - 路由分组 - 路由文件抽离

7.Gin 路由详解 - 路由分组 - 路由文件抽离 前言 在前面的示例中&#xff0c;我们直接将路由的定义全部写在 main.go 文件中&#xff0c;如果后面 路由越来越多&#xff0c;那将会越来越不好管理。 所以&#xff0c;下一步我们应该考虑将路由进行分组管理&#xff0c;并且将其抽…

腾讯云代金券怎么领取(腾讯云代金券在哪领取)

腾讯云代金券是可抵扣费用的优惠券&#xff0c;领券之后新购、续费、升级腾讯云相关云产品可以直接抵扣订单金额&#xff0c;节省购买腾讯云的费用&#xff0c;本文将详细介绍腾讯云代金券的领取方法和使用教程。 一、腾讯云代金券领取 1、新用户代金券【点此领取】 2、老用户…

SVN创建分支

一 从本地创建方式可指定版本号进行分支创建。 1、在本地目录右击 -----> 点击branch/tag(分支/标签) From: 源&#xff0c;可指定具体的版本号&#xff0c; To path: 可通过"..."选择分支路径 最后点击确定&#xff0c;交由服务器执行创建。 二 通过SVN客…

3D 纹理渲染如何帮助设计师有效、清晰地表达设计理念

在线工具推荐&#xff1a; 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数据生成器 - 3D模型在线转换 - 3D模型预览图生成服务 定义 3D 渲染可视化及其用途 3D 可视化是一种艺术形式。这是一个机会。这是进步。借助 3D 纹理…

CNVD-2023-12632:泛微E-cology9 browserjsp SQL注入漏洞复现 [附POC]

文章目录 泛微E-cology9 browserjsp SQL注入漏洞(CNVD-2023-12632)漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 泛微E-cology9 browserjsp SQL注入漏洞(CNVD-2023-12632)漏洞复现 [附POC] 0x…

visionOS空间计算实战开发教程Day 1:环境安装和编写第一个程序

安装 截至目前visionOS还未在Xcode稳定版中开放&#xff0c;所以需要下载​​Xcode Beta版​​。比如我们可以下载Xcode 15.1 beta 2&#xff0c;注意Xcode 15要求系统的版本是macOS Ventura 13.5或更新&#xff0c;也就是说2017年的MacBook Pro基本可以勉强一战&#xff0c;基…

海外IP代理:数据中心代理IP是什么?好用吗?

数据中心代理是代理IP中最常见的类型&#xff0c;也被称为机房IP。这些代理服务器为用户分配不属于 ISP&#xff08;互联网服务提供商&#xff09;而来自第三方云服务提供商的 IP 地址。数据中心代理的最大优势——它们允许在访问网络时完全匿名。 如果你正在寻找海外代理IP&am…