用户登录后端:登录密码解密后用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.rhkb.cn/news/325045.html

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

相关文章

电影院购票管理系统

文章目录 电影院购票管理系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 电影院购票管理系统 一、项目演示 电影院售票管理系统 二、项目介绍 基于springbootvue的前后端分离电影院购票管理…

【linux软件基础知识】如何使用 run_list 字段将任务放入就绪队列中

在给定的代码片段中,struct task_struct 表示内核中任务或进程的进程控制块 (PCB)。 run_list 字段的类型为 struct list_head,这表明它是链表实现的一部分。 run_list字段在Linux内核中常用来表示任务在调度队列中的位置,例如就绪队列或各种优先级队列。 init_task是一个…

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…

Sqlite在Mybatis Plus中关于时间字段的处理

我的个人项目中&#xff0c;使用Mybatis-Plus 和 Sqlite数据库&#xff0c; 但是在存储和查询时间字段的时候&#xff0c;总是出现问题&#xff0c;记录下我解决问题的过程。 Sqlite会默认把时间字段转成时间戳存储到数据库的字段中&#xff0c;看起来不直观&#xff0c;所以我…

刷代码随想录有感(63):将有序数组转换为二叉搜索树(其实时二叉平衡搜索树)

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(vector<int>& nums, int left, int right){if(left > right)return NULL;int mid left (right - left)/2;TreeNode* NewRoot new TreeNode(nums[mid]);NewRoot->left tra…

2024最新从0部署Django项目(nginx+uwsgi+mysql)

云服务器 我这里用的是腾讯云免费试用的2H4Gcentos服务器&#xff08;后升级为2H8G&#xff0c;保险一点提高内存&#xff09; 因为网上很多关于django部属的教程都是宝塔啊&#xff0c;python版本控制器啊这种的&#xff0c;我也误打误撞安装了宝塔面板&#xff0c;但这里我…

【吊打面试官系列】Java高并发篇 - 同步方法和同步块,哪个是更好的选择?

大家好&#xff0c;我是锋哥。今天分享关于 【同步方法和同步块&#xff0c;哪个是更好的选择&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 同步方法和同步块&#xff0c;哪个是更好的选择&#xff1f; 同步块是更好的选择&#xff0c;因为它不会锁住整个对象…

【notepad++】使用

1 notepad 下载路径 https://notepad-plus.en.softonic.com/download 2 设置护眼模式 . 设置——语言格式设置——前景色——黑色 . 背景色——RGB &#xff1a;199 237 204 . 勾选“使用全局背景色”、“使用全局前景色” . 保存并关闭

Apache Flume概述

Apache Flume概述 1.Flume定义 ​ Flume是cloudera(CDH版本的hadoop) 开发的一个分布式、可靠、高可用的海量日志收集系统。 它将各个服务器中的数据收集起来并送到指定的地方去&#xff0c;比如说送到HDFS、Hbase&#xff0c;简单来说flume就是收集日志的。 2.Flume基础架构…

【Web后端】jsp基础知识_请求转发和重定向

1.jsp基础知识 1.1简介 java server page&#xff0c;运行在服务器端的页面java代码html代码java代码全部都放在<%%>中间 1.2jsp表达式 作用&#xff1a;将动态信息显示在页面上&#xff0c;以字符串方式&#xff0c;返回给浏览器端语法&#xff1a;<%变量或表达式…

Debian安装Redis、RabbitMQ、Nacos

安装Redis&#xff1a; 启动Redis、开机自启动 sudo systemctl start redis-server #启动sudo systemctl enable redis-server #开机自启 Redis状态(是否在运行) sudo systemctl status redis-server #查看运行状态 redis-cli ping # 客户端尝试连接 安装RabbitMQ&#xff0c;…

【回溯 网格 状态压缩】52. N 皇后 II

本文涉及知识点 回溯 网格 状态压缩 LeetCode52. N 皇后 II n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回 n 皇后问题 不同的解决方案的数量。 示例 1&#xff1a; 输入&#x…

conan2 基础入门(02)-安装

conan2 基础入门(02)-安装 文章目录 conan2 基础入门(02)-安装⭐前言⭐安装python安装安装包安装自行操作 ⭐验证配置环境变量命令行验证conan配置文件 END ⭐前言 Conan 2.0: C and C Open Source Package Manager 官方提供三种安装conan的方式。分别为&#xff1a; Recommen…

1290.二进制链表转整数

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。 请你返回该链表所表示数字的 十进制值 。 示例 1&#xff1a; 输入&#xff1a;head [1,0,1] 输出&#xff1a;5 解释&#xff1a;二进制数 (101) 转化为十进制…

在k8s中部署Prometheus并实现对k8s集群的监控

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Prometheus&#xff1a;监控的神》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、k8s简介 2、 Prometheus概述 二、准备k8s环境 1、…

IDEA安装使用Git

IDEA安装使用Git 1 Git下载与安装 2 在IDEA中使用Git 2.1 IDEA中配置Git 在IDEA中使用Git&#xff0c;本质上还是使用本地安装的Git软件&#xff0c;所以需要在IDEA中配置Git。 2.2 在IDEA中使用Git 2.2.1 获取Git仓库 在IDEA中使用Git获取仓库有两种方式: 本地初始化仓库从…

HTTP超时时间设置

在进行超时时间设置之前我们需要了解一次http请求经历的过程 浏览器进行DNS域名解析&#xff0c;得到对应的IP地址根据这个IP&#xff0c;找到对应的服务器建立连接&#xff08;三次握手&#xff09;建立TCP连接后发起HTTP请求&#xff08;一个完整的http请求报文&#xff09;服…

在R的 RGui中,使用devtools 安装trajeR

创建于&#xff1a;2024.5.5 文章目录 1. 报错信息2. 尝试使用指定的清华镜像&#xff0c;没有解决3. 找到原因&#xff1a;官网把包删除了4. 尝试从网上下载&#xff0c;然后安装。没有成功5. 使用devtools安装5.1 尝试直接安装&#xff1a;install.packages("devtools&q…

Vue从入门到实战Day04

一、组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; 1. scoped样式冲突 默认情况&#xff1a;写在组件中的样式会全局生效 -> 因此很容易造成多个组件之间的样式冲突问题。 1. 全局样式&#xff1a;默认组件中的样式会作用到全局 2. 局部样式&#xff1a;可以…

浅谈运维数据安全

在数字化日益深入的今天&#xff0c;运维数据安全已经成为企业信息安全体系中的核心要素。运维工作涉及到企业信息系统的各个方面&#xff0c;从硬件维护到软件升级&#xff0c;从网络配置到数据备份&#xff0c;无一不需要严谨的数据安全保障措施。本文将从运维数据安全的重要…