springboot企业级抽奖项目业务一(登录模块)

开发流程

该业务基于rouyi生成好了mapper和service的代码,现在需要在controller层写接口

实际操作流程:

看接口文档一>controller里定义函数一>看给出的工具类一>补全controller里的函数一>运行测试

接口文档

在登录模块有登录和登出方法

登录分出登录成功、账号密码错误、密码多次错误三种情况

登出点了一定登出成功

controller里定义

在注解框架里加上login和logout两个函数

@RestController
@RequestMapping(value = "/api")
@Api(tags = {"登录模块"})
public class LoginController {@Autowiredprivate CardUserService userService;@Autowiredprivate RedisUtil redisUtil;@PostMapping("/login")@ApiOperation(value = "登录")@ApiImplicitParams({@ApiImplicitParam(name="account",value = "用户名",required = true),@ApiImplicitParam(name="password",value = "密码",required = true)})public ApiResult login(HttpServletRequest request, @RequestParam String account,@RequestParam String password) {//TODOreturn null;}@GetMapping("/logout")@ApiOperation(value = "退出")public ApiResult logout(HttpServletRequest request) {//TODOreturn null;}}

看给出的工具类

找该模块附近的common和util包

补全controller里的函数

login部分

首先拿到用户(基于rouyi使用的mybatis-plus)

QueryWrapper<CardUser> wrapper = new QueryWrapper<>();
wrapper.eq("uname",account).eq("passwd",PasswordUtil.encodePassword(password));
List<CardUser> users = userService.list(wrapper);
  1. QueryWrapper<CardUser> wrapper = new QueryWrapper<>();

    创建一个 QueryWrapper 对象 wrapper,用于构建查询条件。
  2. wrapper.eq("uname",account).eq("passwd",PasswordUtil.encodePassword(password));

    使用 wrapper 对象的 eq 方法添加查询条件,这里表示查询条件为用户名("uname" 字段)等于 account 变量的值,并且密码("passwd" 字段)等于经过加密后的 password 变量的值。
  3. List<CardUser> users = userService.list(wrapper);

    通过 UserService 的 list 方法传入包含查询条件的 wrapper 对象,执行数据库查询操作,返回符合条件的 CardUser 对象列表 users。这里为什么要用wrapper获取满足条件的用户列表,再取第一个呢?可以直接CardUser user = userService.getOne(wrapper);吗?这是一种保护措施。万一数据有多条不会出错。getOne的话就报错了。用getOne然后捕获异常也可以的。

然后处理登录成功的情况

if (users != null && users.size() > 0) {CardUser user = users.get(0);user.setIdcard(null);user.setPasswd(null);HttpSession session = request.getSession();session.setAttribute("user", user);return new ApiResult(1, "登录成功", user);
}

         if (users != null && users.size() > 0)

  1. users != null: 这一部分是为了确保 users 不为 null,即确保查询返回的用户列表对象不为空。如果 users 为 null,那么调用 users.size() 方法将会导致空指针异常。因此,这一部分判断是为了避免空指针异常。

  2. users.size() > 0: 这一部分判断是为了确保 users 列表中至少包含一个用户。即使 users 不为 null,但如果其中没有任何用户,也不应该继续处理和返回登录成功的信息,因为没有符合条件的用户。

  1. CardUser user = users.get(0);

    从查询到的用户列表中获取第一个用户对象,并赋值给 user 变量。
  2. user.setIdcard(null);

    将用户对象的身份证号字段设置为 null,出于安全考虑避免将密码信息传递到前端。
  3. user.setPasswd(null);

    将用户对象的密码字段设置为 null,同样可能是出于安全考虑。
  4. HttpSession session = request.getSession();

    通过 request 对象获取 HttpSession 对象,用于存储用户的会话信息。
  5. session.setAttribute("user", user);

    将处理后的用户对象存储到 HttpSession 中,以键值对 "user"-"user" 的形式保存。
  6. return new ApiResult(1, "登录成功", user);

    最后返回一个 ApiResult 对象,其中包含了状态码、消息和用户对象,用于向前端传递登录成功的信息和用户数据。

接下来处理登录失败的情况

对于密码错误5次的处理

Integer errortimes = (Integer) redisUtil.get(RedisKeys.USERLOGINTIMES + account);
if (errortimes != null && errortimes >= 5) {return new ApiResult(0, "密码错误5次,请5分钟后再登录", null);
}

从 Redis 中获取用户登录错误次数 errortimes,然后判断如果 errortimes 不为 null 而且大于等于 5,则返回一个包含错误提示信息的 ApiResult 对象,告知用户密码错误达到5次,需要等待5分钟后再尝试登录。

redisUtil.get(RedisKeys.USERLOGINTIMES + account) 表示根据用户账号构建的键名从 Redis 中获取该用户的登录错误次数信息。如果 Redis 中存储了该信息,则返回相应的错误次数;如果不存在或者 Redis 出现问题,则可能返回 null。。

  • RedisKeys.USERLOGINTIMES: 这是一个 Redis Key 的前缀,用于标识存储用户登录错误次数的键名。
  • account: 这是用户的账号信息,用于构建特定用户的登录错误次数的键名。

然后在判断流程增加密码错误的处理

else {redisUtil.incr(RedisKeys.USERLOGINTIMES + account, 1);redisUtil.expire(RedisKeys.USERLOGINTIMES + account, 60 * 5);return new ApiResult(0, "账户名或密码错误", null);
}

如果用户登录失败(且不满足之前判断的密码错误次数达到5次的条件),则会将该用户的登录错误次数加1,并设置该键的过期时间为5分钟。然后返回一个包含账户名或密码错误信息的 ApiResult 对象。

完整代码

@Autowired
private CardUserService userService;@Autowired
private RedisUtil redisUtil;@PostMapping("/login")
@ApiOperation(value = "登录")
@ApiImplicitParams({@ApiImplicitParam(name="account",value = "用户名",required = true),@ApiImplicitParam(name="password",value = "密码",required = true)
})
public ApiResult login(HttpServletRequest request, @RequestParam String account, @RequestParam String password) {Integer errortimes = (Integer) redisUtil.get(RedisKeys.USERLOGINTIMES + account);if (errortimes != null && errortimes >= 5) {return new ApiResult(0, "密码错误5次,请5分钟后再登录", null);}QueryWrapper<CardUser> wrapper = new QueryWrapper<>();wrapper.eq("uname", account).eq("passwd", PasswordUtil.encodePassword(password));List<CardUser> users = userService.list(wrapper);if (users != null && users.size() > 0) {CardUser user = users.get(0);user.setIdcard(null);user.setPasswd(null);HttpSession session = request.getSession();session.setAttribute("user", user);return new ApiResult(1, "登录成功", user);} else {redisUtil.incr(RedisKeys.USERLOGINTIMES + account, 1);redisUtil.expire(RedisKeys.USERLOGINTIMES + account, 60 * 5);return new ApiResult(0, "账户名或密码错误", null);}
}

logout部分

非常简单粗暴

HttpSession session = request.getSession();
if (session != null) {session.invalidate();
}
return new ApiResult(1, "退出登录", null);

首先通过HttpServletRequest获取HttpSession对象,然后检查session是否为null,如果不为null,则调用invalidate()方法使session失效。最后返回一个表示成功退出登录的ApiResult对象。

让session失效是为了确保用户在退出登录后,其会话信息得到及时清理,从而避免可能存在的安全风险和信息泄漏问题。一旦会话失效,用户在该会话中的所有状态和数据都会被清除,包括登录凭证、用户信息等,以确保用户的隐私和安全。

完整代码

@GetMapping("/logout")
@ApiOperation(value = "退出")
public ApiResult logout(HttpServletRequest request) {HttpSession session = request.getSession();if (session != null) {session.invalidate();}return new ApiResult(1, "退出登录", null);
}

运行测试

运行springboot项目后访问http://localhost:9001/doc.html

密码正确的情况

密码错误的情况

密码错5次及以上的情况

使用nginx部署前端后,进行前后端联调:

登录成功还没跳转

登录失败:

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

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

相关文章

扫雷(蓝桥杯,acwing)

题目描述&#xff1a; 扫雷是一种计算机游戏&#xff0c;在 2020 世纪 80 年代开始流行&#xff0c;并且仍然包含在某些版本的 Microsoft Windows 操作系统中。 在这个问题中&#xff0c;你正在一个矩形网格上玩扫雷游戏。 最初网格内的所有单元格都呈未打开状态。 其中 M个…

(附源码)基于Spring Boot + Vue的校园综合信息服务平台设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31…

牛客NC196 编辑距离(一)【较难 DFS/DP,动态规划,样本对应模型 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/6a1483b5be1547b1acd7940f867be0da 思路 编辑距离问题 什么是两个字符串的编辑距离&#xff08;edit distance&#xff09;&#xff1f;给定字符串s1和s2&#xff0c;以及在s1上的如下操作&#xff1a;插入&…

基于springboot的大学生租房平台系统

技术&#xff1a;springbootmysqlvue 一、系统背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对大学生租房信息管理混乱…

基于小波神经网络的回归分析,基于ANN的回归分析

目标 背影 BP神经网络的原理 BP神经网络的定义 BP神经网络的基本结构 BP神经网络的神经元 BP神经网络的激活函数, BP神经网络的传递函数 小波神经网络(以小波基为传递函数的BP神经网络) 代码链接:小波神经网络回归分析,小波分解+BP神经网络-机器学习文档类资源-CSDN文库 …

Nginx:部署及配置详解(linux)

Nginx&#xff1a;部署及配置详解&#xff08;linux&#xff09; 1、nginx简介2、安装编译工具及库文件3、安装 pcre4、nginx安装5、nginx配置文件nginx.conf组成6、nginx配置实例-反向代理7、nginx 配置实例-负载均衡 &#x1f496;The Begin&#x1f496;点点关注&#xff0c…

长连接技术

个人学习记录&#xff0c;欢迎指正 1.轮询 1.1 轮询的形式 短连接轮询 前端每隔一段时间向服务端发起一次Http请求来获取数据。 const shortPolling () > { const intervalHandler setInterval(() > {fetch(/xxx/yyy).then(response > response.json()).then(respo…

HarmonyOS NEXT应用开发之跨文件样式复用和组件复用

介绍 本示例主要介绍了跨文件样式复用和组件复用的场景。在应用开发中&#xff0c;我们通常需要使用相同功能和样式的ArkUI组件&#xff0c;例如购物页面中会使用相同样式的Button按钮、Text显示文字&#xff0c;我们常用的方法是抽取公共样式或者封装成一个自定义组件到公共组…

力扣4寻找两个正序数组的中位数

1.实验内容 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 2.实验目的 算法的时间复杂度应该为 O(log (mn)) 。 3.基本思路 碰到时间复杂度要求log的&#xff0c;肯定用二分查找&…

【Markdown】【mermaid】Mermaid流程图基础语法Flowcharts - Basic Syntax

流程图 - 基础语法 流程图简介节点默认节点带文本的节点Unicode 文本Markdown 格式化 流程图方向节点形状圆角矩形节点体育场形节点子程序形节点圆柱形节点圆形节点不对称节点菱形节点六边形节点平行四边形节点另一种平行四边形节点梯形节点另一种梯形节点双圆节点 节点之间的连…

shell编程入门(笔记)

1、shell编程基础&#xff1a; 1.1、shell的解释执行功能 1.2、什么是shell程序&#xff1f; 1.3、shell程序编程的主要内容 1.4、shell程序的第一行 1.5、变量要求 1.6、环境变量和只读变量 1.7、位置参量 1.8、位置参量列表 1.9、数组 2、输入输出 2.1、输入-read命令 2.2…

Pytest用例间参数传递的两种实现方式示例

前言 我们在做接口自动化测试的时候&#xff0c;会经常遇到这种场景&#xff1a;接口A的返回结果中的某个字段&#xff0c;是接口B的某个字段的入参。如果是使用postman&#xff0c;那我们可以通过设置后置变量&#xff0c;然后在需要使用的地方通过{{}}的方式来进行调用。但是…

[LLM]大模型基础知识点--大模型与LLM

1、什么是大模型&#xff1f; 定义&#xff1a;在机器学习领域&#xff0c;"大模型"通常指的是拥有大量参数的深度学习模型。这些模型通常由数十亿甚至数千亿个参数组成。 特点&#xff1a;由于参数众多&#xff0c;这些模型能够从大量数据中学习复杂的模式和关系。…

OJ : 1087 : 获取出生日期(多实例测试)

题目描述 输入某人的18位身份证号&#xff0c;输出其出生日期。 输入 多实例测试。首先输入一个整数n&#xff0c;表示测试实例的个数&#xff0c;然后是n行&#xff0c;每行是一个18位身份证号。 输出 对于输入的每个身份证号&#xff0c;输出一行&#xff0c;即其对应的…

SpringMVC 的运行流程

Spring MVC 是一个基于 MVC 设计模式的 Web 框架&#xff0c;它提供了一种优雅的方式来构建 Web 应用程序&#xff0c;将应用程序的不同部分分离开来&#xff0c;以便更好地管理和维护。了解 Spring MVC 的运行流程对于理解它的工作原理以及在实际项目中的应用非常重要。 1. 请…

银行卡账户交易异常已被限制部分功能,怎么办?

文章目录 I 解决方案1.1 限制原因1.2 防范1.3 案例1.4 用卡安全小知识II 个人账户收款监管规则III 反诈提醒I 解决方案 处理非柜面交易限制,只能到开户行柜台申请解除。异地卡的,需要联系开户行,提供相关资料。有些地方银行的,比如长沙银行,可以使用线上柜台进行审核。先到…

# termux连接云服务器

termux使用 pkg install openssh 连接服务器 ssh root39.100.181.23 安装postgres

不满足软件包要求‘transformers==4.30.2‘, ‘sse-starlette

transformers4.30.2支持的SSE-Starlette版本是0.14.0

Flume入门概述及安装部署

目录 一、Flume概述1.1 Flume定义1.2 Flume基础架构 二、Flume安装部署 一、Flume概述 1.1 Flume定义 Flume是Cloudera提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构&#xff0c;灵活简单。 1.2 Flume基础…

Python实现计算复读次数(附带源码)

在Python中&#xff0c;可以使用以下几种方法计算复读次数&#xff1a; 方法一&#xff1a;使用count()函数 count()函数用于统计字符串中某个字符或子字符串出现的次数。 示例&#xff1a; Python # 计算字符串中 "a" 出现的次数 count "hello world&quo…