用户登录后端:登录密码解密后用PasswordEncoder验证密码是否正确

前置知识:
前端登录加密看用户登录
PasswordEncoder加密看PasswordEncoder详解

项目中因为要判断用户登录密码是否正确,通过输入错误次数锁住用户

1.后端配置rsa私钥

#密码加密传输,前端公钥加密,后端私钥解密
rsa:private_key: xxxx

2. 读取配置文件

/**  Copyright 2019-2020 Zheng Jie**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/
package com.njry.config;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** @author Zheng Jie* @website https://eladmin.vip* @description* @date 2020-05-18**/
@Data
@Component
public class RsaProperties {public static String privateKey;@Value("${rsa.private_key}")public void setPrivateKey(String privateKey) {RsaProperties.privateKey = privateKey;}
}

3. Rsa 工具类

package com.njry.utils;import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/*** @author https://www.cnblogs.com/nihaorz/p/10690643.html* @description Rsa 工具类,公钥私钥生成,加解密* @date 2020-05-18**/
public class RsaUtils {private static final String SRC = "123456";public static void main(String[] args) throws Exception {System.out.println("\n");RsaKeyPair keyPair = generateKeyPair();System.out.println("公钥:" + keyPair.getPublicKey());System.out.println("私钥:" + keyPair.getPrivateKey());System.out.println("\n");test1(keyPair);System.out.println("\n");test2(keyPair);System.out.println("\n");}/*** 公钥加密私钥解密*/private static void test1(RsaKeyPair keyPair) throws Exception {System.out.println("***************** 公钥加密私钥解密开始 *****************");String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);System.out.println("加密前:" + RsaUtils.SRC);System.out.println("加密后:" + text1);System.out.println("解密后:" + text2);if (RsaUtils.SRC.equals(text2)) {System.out.println("解密字符串和原始字符串一致,解密成功");} else {System.out.println("解密字符串和原始字符串不一致,解密失败");}System.out.println("***************** 公钥加密私钥解密结束 *****************");}/*** 私钥加密公钥解密* @throws Exception /*/private static void test2(RsaKeyPair keyPair) throws Exception {System.out.println("***************** 私钥加密公钥解密开始 *****************");String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);System.out.println("加密前:" + RsaUtils.SRC);System.out.println("加密后:" + text1);System.out.println("解密后:" + text2);if (RsaUtils.SRC.equals(text2)) {System.out.println("解密字符串和原始字符串一致,解密成功");} else {System.out.println("解密字符串和原始字符串不一致,解密失败");}System.out.println("***************** 私钥加密公钥解密结束 *****************");}/*** 公钥解密** @param publicKeyText 公钥* @param text 待解密的信息* @return /* @throws Exception /*/public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, publicKey);byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));return new String(result);}/*** 私钥加密** @param privateKeyText 私钥* @param text 待加密的信息* @return /* @throws Exception /*/public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());return Base64.encodeBase64String(result);}/*** 私钥解密** @param privateKeyText 私钥* @param text 待解密的文本* @return /* @throws Exception /*/public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));return new String(result);}/*** 公钥加密** @param publicKeyText 公钥* @param text 待加密的文本* @return /*/public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());return Base64.encodeBase64String(result);}private static byte[] doLongerCipherFinal(int opMode,Cipher cipher, byte[] source) throws Exception {ByteArrayOutputStream out = new ByteArrayOutputStream();if (opMode == Cipher.DECRYPT_MODE) {out.write(cipher.doFinal(source));} else {int offset = 0;int totalSize = source.length;while (totalSize - offset > 0) {int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset);out.write(cipher.doFinal(source, offset, size));offset += size;}}out.close();return out.toByteArray();}/*** 构建RSA密钥对** @return /* @throws NoSuchAlgorithmException /*/public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());return new RsaKeyPair(publicKeyString, privateKeyString);}/*** RSA密钥对对象*/public static class RsaKeyPair {private final String publicKey;private final String privateKey;public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}public String getPublicKey() {return publicKey;}public String getPrivateKey() {return privateKey;}}
}

4. 用户登录controller

 @Log("用户登录")@ApiOperation("登录授权")@AnonymousPostMapping(value = "/login")public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {// 密码解密String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());String username = authUser.getUsername();String ip = StringUtils.getIp(request);String browser = StringUtils.getBrowser(request);
//        String address = StringUtils.getCityInfo(ip);//        1.验证当前ip是否锁定List<SysIpLock> sysIpLock = sysIpLockService.findByIp(ip);// 获取当前日期的Date对象Date currentDate = new Date();if(sysIpLock != null &&  sysIpLock.size() > 0){
//            ip多个信息里找最新的一个锁过期时间判断SysIpLock sysIpLockFrist = sysIpLock.get(0);if(sysIpLockFrist.getIpLockTime().compareTo(currentDate) > 0){throw new BadRequestException("ip已锁定,稍后再试");}else{
//              有ip锁记录,但是释放了,依旧要查用户List<SysIpLock> sysIpLockList = sysIpLockService.findLockByUserName(username);if(sysIpLockList != null &&  sysIpLockList.size() > 0){
//              账号多个信息里找最新的一个锁过期时间判断SysIpLock sysIpLock1 = sysIpLockList.get(0);if(sysIpLock1.getLockDateEnd().compareTo(currentDate) > 0){throw new BadRequestException("账号已锁定,稍后再试");}}}}else{
//        2.验证用户是否锁定
//        2.1先去sys_ip_lock里看用户是否锁定List<SysIpLock> sysIpLockList = sysIpLockService.findLockByUserName(username);if(sysIpLockList != null &&  sysIpLockList.size() > 0){
//            账号多个信息里找最新的一个锁过期时间判断SysIpLock sysIpLockFrist = sysIpLockList.get(0);if(sysIpLockFrist.getLockDateEnd().compareTo(currentDate) > 0){throw new BadRequestException("账号已锁定,稍后再试");}}}//比较密码
//        根据用户名获取数据库密码---判断用户是否输入正确密码String encode = userService.findByUserName(username);boolean matches = passwordEncoder.matches(password,encode);SysLog sysLog = new SysLog("LOGIN",System.currentTimeMillis());
//        密码正确与否都交给下面框架jwt搞定,这里负责记录登录日志sysLogService.saveLog(username, browser, ip, sysLog, matches);if(matches){// 保存登录信息(redis)
//            loginUserLockService.save(authUser.getUsername(),0,request);}else{// 保存登录信息(redis)
//        loginUserLockService.save(authUser.getUsername(),1, request);
//            判断log表一段时间内是否超过用户输入密码错误次数,Timestamp timestampNow = new Timestamp(System.currentTimeMillis());Timestamp timestampNowNoCalendar = new Timestamp(System.currentTimeMillis());// 使用Calendar进行时间计算Calendar calendar = Calendar.getInstance();calendar.setTime(timestampNowNoCalendar);calendar.add(Calendar.HOUR, 2); // 在当前时间上加两个小时Calendar calendarAgain = Calendar.getInstance();calendarAgain.setTime(timestampNowNoCalendar);calendarAgain.add(Calendar.HOUR, -2); // 在当前时间上减去两个小时// 获取加两个小时后的TimestampTimestamp twoHoursLater = new Timestamp(calendar.getTimeInMillis());// 获取加两个小时前的TimestampTimestamp twoHoursBefore = new Timestamp(calendarAgain.getTimeInMillis());Integer usernameFailNumber = sysLogService.findFailCountByUsername(username,timestampNow,twoHoursBefore);Integer ipFailNumber = sysLogService.findFailCountByIp(ip,timestampNow,twoHoursBefore);
//            超过失败次数就想记录ip和username的sys_ip_lock表加锁记录if(usernameFailNumber >= 3){SysIpLock sysIpLock1 = new SysIpLock();sysIpLock1.setUsername(username);sysIpLock1.setLockPwd(true);sysIpLock1.setLockType(false);sysIpLock1.setLockDateEnd(twoHoursLater);
//                ip这两个字段设置not nullsysIpLock1.setIp(ip);sysIpLock1.setIpStatus(false);sysIpLockService.create(sysIpLock1);
//                sysIpLockService.save(sysIpLock1);}if(ipFailNumber >= 6){SysIpLock sysIpLock2 = new SysIpLock();sysIpLock2.setIp(ip);sysIpLock2.setLockType(true);sysIpLock2.setIpStatus(true);sysIpLock2.setIpLockTime(twoHoursLater);
//                插入无用的username失败状态sysIpLock2.setUsername(username);sysIpLock2.setLockPwd(false);sysIpLockService.create(sysIpLock2);
//                sysIpLockService.save(sysIpLock2);}}// 查询验证码String code = (String) redisUtils.get(authUser.getUuid());// 清除验证码redisUtils.del(authUser.getUuid());if (StringUtils.isBlank(code)) {throw new BadRequestException("验证码不存在或已过期");}if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {throw new BadRequestException("验证码错误");}UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);SecurityContextHolder.getContext().setAuthentication(authentication);// 生成令牌与第三方系统获取令牌方式// UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());// Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());// SecurityContextHolder.getContext().setAuthentication(authentication);String token = tokenProvider.createToken(authentication);final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();// 返回 token 与 用户信息Map<String, Object> authInfo = new HashMap<String, Object>(2) {{put("token", properties.getTokenStartWith() + token);put("user", jwtUserDto);}};if (loginProperties.isSingleLogin()) {// 踢掉之前已经登录的tokenonlineUserService.kickOutForUsername(authUser.getUsername());}// 保存在线信息onlineUserService.save(jwtUserDto, token, request);// 返回登录信息return ResponseEntity.ok(authInfo);}

controller里面关于密码的(接着是ip和用户是否锁定暂时不看)
在这里插入图片描述

在这里插入图片描述

总结

这只是用户登录处理简单处理,重头戏是Security认证流程用户登录:断点看流程认证

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

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

相关文章

Hive 特殊的数据类型 Array、Map、Struct

Array 数组类型&#xff0c;存储数据类型一致的列表数据。 我们可以使用 array 方法来创建一个数组&#xff0c;如下所示&#xff1a; select array(1,2,3,4,5);如果其中的数据类型不一致&#xff0c;那么它会转换成统一的数据类型&#xff08;前提是能够进行转换&#xff0…

Coze扣子开发指南:AI零代码编程创建插件

在Coze扣子中创建插件&#xff0c;有两种方式&#xff0c;一是用API&#xff0c;具体方式参照上一篇文章《Coze扣子开发指南&#xff1a;用免费API自己创建插件》&#xff0c;还有一种方式就是编程&#xff0c;不过有了AI的帮助&#xff0c;即使不会编程的人&#xff0c;也可以…

针对 % 号 | 引起的 不安全情况

把网站开放的课程都检索下来了 一、情况1 org.apache.tomcat.util.http.Parameters processParameters 信息: Character decoding failed. Parameter [Mac] with value [%%%] has been ignored. Note that the name and value quoted here may be corrupted due to the failed…

猜猜歇后语

页面 在输入框中填写你猜的答案&#xff0c;点击“显示答案”按钮&#xff0c;显示正确答案。 页面代码 function showAnswer(element){var elem$(element);elem.next().show();} //# // 初始化DataGrid对象 $(#dataGrid).dataGrid({searchForm: $(#searchForm),columnModel:…

音视频-H264编码封装- MP4格式转Annex B格式

目录 1&#xff1a;H264语法结构回顾 2&#xff1a;H264编码补充介绍 3&#xff1a;MP4模式转Annex B模式输出到文件示例 1&#xff1a;H264语法结构回顾 在之前文章里介绍过H264的语法结构。 传送门: 视音频-H264 编码NALU语法结构简介 2&#xff1a;H264编码补充介绍 H…

Web自动化-日志收集

目标 1. 理解日志的相关概念 2. 掌握日志的基本用法 3. 掌握日志的高级用法 一、日志相关概念 目标 1. 了解日志的概念 2. 理解日志的作用 3. 掌握常见的日志级别 1. 日志 概念&#xff1a;日志就是用于记录系统运行时的信息&#xff0c;对一个事件的记录&#xff1b…

Springboot+Vue项目-基于Java+MySQL的制造装备物联及生产管理ERP系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Jenkins 备份恢复插件 ThinBackup

系统环境&#xff1a; Jenkins 版本&#xff1a;2.213 一、简介 在部署完 Jenkins 后首先要准备的就是数据备份问题&#xff0c;尤其是在生产环境下的 Jenkins&#xff0c;如果数据丢失很可能导致项目上线和开发时间受到影响&#xff0c;所以备份数据很重要。还好&#xff0c;…

【DevOps】Linux 安全:iptables 组成、命令及应用场景详解

导读&#xff1a;全面掌握 iptables&#xff1a;从基础到实践 在 Linux 系统中&#xff0c;iptables 是一个非常强大的工具&#xff0c;它不仅是系统管理员用来构建和管理网络防火墙的首选工具&#xff0c;而且也是一个功能丰富的网络流量处理系统。无论是进行包过滤、监控网络…

韩顺平0基础学Java——第9天

p169-201 数组&#xff08;第六章&#xff09; 数组扩容 此时原来的数组arr被销毁。 牛蛙&#xff1a; 最后再加一句 SYstem。out。println&#xff08;“是否添加&#xff1f;”&#xff09;&#xff1b; char key myscanner。netx&#xff08;&#xff09;。charAT&…

AI写作推荐-写文ai-AI在线写作生成器-3步完成写作任务

AI写作利器&#xff1a;推荐几款神助攻文案创作工具 随着技术的进步&#xff0c;人工智能&#xff08;AI&#xff09;已达到高级水平&#xff0c;在众多领域展现其强大能力。 在文本创作的领域&#xff0c;人工智能&#xff08;AI&#xff09;应用已显著地提升了写作效率和创意…

【Python-爬虫】

Python-爬虫 ■ 爬虫分类■ 1. 通用网络爬虫&#xff1a;&#xff08;搜索引擎使用&#xff0c;遵守robots协议&#xff09;■ robots协议&#xff08;君子协议&#xff09; ■ 2. 聚集网络爬虫&#xff1a;自己写的爬虫程序 ■ urllib.request&#xff08;要导入的模块&#x…

2024年4月12日饿了么春招实习试题【第三题】-题目+题解+在线评测,2024.4.12,饿了么机试【Kruskal 算法, 最小生成树】

2024年4月12日饿了么春招实习试题【第三题】-题目题解在线评测&#xff0c;2024.4.12&#xff0c;饿了么机试 &#x1f3e9;题目一描述&#xff1a;样例1样例2解题思路一&#xff1a;[Kruskal 算法](https://baike.baidu.com/item/%E5%85%8B%E9%B2%81%E6%96%AF%E5%8D%A1%E5%B0%…

图像融合-下游任务(目标检测、实例分割、深度估计、局部区域细节放大)

下游任务: 采用目标检测、实例分割和深度估计的下游任务来验证图像融合结果质量。 文章目录 下游任务:1.目标检测2.实例分割3.深度估计局部细节放大工具Update1.目标检测 YOLOv8:https://github.com/ultralytics/ultralytics 步骤内容第一步下载项目到本地第二步安装READ…

前端笔记-day05

文章目录 01-结构伪类选择器02-结构伪类选择器-公式用法03-伪元素选择器04-盒子模型-组成05-盒子模型-边框线06-盒子模型-单方向边框线07-盒子模型-内边距08-盒子模型-padding多值写法09-盒子模型-尺寸计算10-盒子模型-版心居中11-清除默认样式12-元素溢出overflow13-外边距合并…

【半夜学习MySQL】数据库中的数据类型(含数值类型、文本二进制类型、时间类型、String类型详谈)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 数据类型分类数值类型bit类型tinyint类型int类型float类型decimal类型 文本、二进制类型char类型varchar类型 时间类型Strin…

【目标检测论文解读复现NO.37】基于改进的 YOLOv8 变电设备红外图像检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

PG 检查点管理与Oracle的比较

之前介绍过&#xff0c;在任何数据库中&#xff0c;一条DML操作执行都需要在内存中执行&#xff0c;但当操作越来越多&#xff0c;总有时候内存会写满&#xff0c;这时候就需要把内存中的块写入到磁盘&#xff0c;释放内存&#xff0c;保存数据。 写入到磁盘这一步&#xff0c;…

安全工程师面试题

安全工程师面试题安全工程师是一个非常重要的职位&#xff0c;他们负责保护公司的网络和系统免受黑客和恶意软件的攻击。如果你想成为一名安全工程师&#xff0c;那么你需要准备好面试。下面是一… 1安全工程师面试题 安全工程师是一个非常重要的职位&#xff0c;他们负责保护…

SpringSecurity集成第三方登录

SpringSecurity 集成第三方登录 认证及自定义流程 首先我们提供一个实现了AbstractAuthenticationProcessingFilter抽象类的过滤器&#xff0c;用来代替UsernamePasswordAuthenticationFilter逻辑&#xff0c;然后提供一个AuthenticationProvider实现类代替AbstractUserDetail…