用户登录后端:登录密码解密后用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.mzph.cn/bicheng/10921.shtml

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

相关文章

基于C++基础知识的指针

一、变量与指针 在C中&#xff0c;变量是用来存储数据的一个标识符&#xff0c;而指针是一个变量&#xff0c;该变量存储的是另一个变量的地址。 变量可以是不同的数据类型&#xff0c;包括整数&#xff08;int&#xff09;、浮点数&#xff08;float&#xff09;、字符&#…

智慧粮库/粮仓视频监管系统:AI视频智能监测保障储粮安全

智慧粮库视频监管系统是一种基于物联网、AI技术和视频监控技术的先进管理系统&#xff0c;主要用于对粮食储存环境进行实时监测、数据分析和预警。TSINGSEE青犀智慧粮库/粮仓视频智能管理系统方案通过部署多区域温、湿度、空气成分等多类传感器以及视频监控等设施&#xff0c;对…

IDEA及Maven配置代理及Maven中央仓库配置详解

一、配置代理 首先&#xff0c;需要本地开启代理入口&#xff0c;如图。 这个跟你使用代理软件有关。像我使用的是qv2ray。 其次&#xff0c;idea配置代理&#xff0c;如图。 1.1 idea配置代理 打开Settings&#xff0c;如图 1.2 maven配置代理 maven配置代理&#xff0c;修…

虚拟机CentOS密码重置

1&#xff0c;reboot重启 在出现下面的界面1按e 如果有选项就选择“CentOS Linux &#xff08;3.10.0-327.e17.x86_64&#xff09;7 &#xff08;Core&#xff09;”【我的电脑没有直接显示界面2】 界面1 界面2 2&#xff0c;在上述界面2中继续按e进入编辑模式 找到“ro cr…

partially initialized module ‘replicate‘ has no attribute ‘run‘

partially initialized module replicate has no attribute run(most likely due to a circular import) 在包名上停留查看impot 包的地址。 报错原因&#xff1a; 文件重名了&#xff0c;导入了 当前文件 。 修改文件名 即可。

Vue3路由及登录注销功能、设置导航守护功能模块

路由 在vue中&#xff0c;页面和组件都是.vue文件&#xff0c;可以说是一样的&#xff0c;结构、内容和生产方法都是一样&#xff0c;但是组件可以被反复使用&#xff0c;但页面一般只被使用一次。 路由的作用就是网页地址发生变化时&#xff0c;在App.vue页面的指定位置可以加…

17 M-LAG 配置思路

16 华三数据中心最流行的技术 M-LAG-CSDN博客 M-LAG 配置思路 什么是M-LAG&#xff1f;为什么需要M-LAG&#xff1f; - 华为 (huawei.com) 1 配置 M-LAG 的固定的MAC地址 [SW-MLAG]m-lag system-mac 2-2-2 2 配置M-LAG 的系统标识符系统范围1到2 [SW-MLAG]m-lag system-nu…

MongoDB安装及接入springboot

环境&#xff1a;windows、jdk8、springboot2 1.MongoDB概述 MongoDB是一个开源、高性能、无模式&#xff08;模式自由&#xff09;的文档&#xff08;Bson&#xff09;型数据库&#xff1b;其特点如下&#xff1a; 模式自由 ---- 不需要提前创建表 直接放数据就可以 支持高并…

STM32窗口看门狗的操作

STM32的窗口看门狗的主要功能是&#xff0c;程序过早的喂狗还有太晚喂狗&#xff0c;都会触发单片机重启&#xff0c;就是有一个时间段&#xff0c;在这个时间段内喂狗才不会触发单片机重启。 下面我就总结一下窗口看门狗的设置过程&#xff1a; 第一步&#xff1a;开启窗口看…

vscode怎么设置背景图片?

vscode背景图片是可以自己设置的&#xff0c;软件安装后默认背景的颜色是黑色的&#xff0c;这是默认的设计&#xff0c;如果要修改背景为指定的图片&#xff0c;那么我们需要安装插件&#xff0c;然后再通过代码来设置背景图片的样式&#xff0c;下面我们就来看看详细的教程。…

代数结构:5、格与布尔代数

16.1 偏序与格 偏序集&#xff1a;设P是集合&#xff0c;P上的二元关系“≤”满足以下三个条件&#xff0c;则称“≤”是P上的偏序关系&#xff08;或部分序关系&#xff09; &#xff08;1&#xff09;自反性&#xff1a;a≤a&#xff0c;∀a∈P&#xff1b; &#xff08;2…

旅游推荐管理系统(小组项目)

文章目录 前言 一、项目介绍 1. 项目目的 2. 项目意义 2.1 提升旅游体验 2.2 促进旅游业发展 2.3 数据积累与分析 2.4 提升服务品质 2.5 优化资源配置 二、项目结构 1. 主要使用的技术 1.1 若依&#xff08;Ruoyi&#xff09;框架 1.2 Vue.js框架 1.3 Ajax 1.4 …

【进程通信】了解信号以及信号的产生

文章目录 0.前言1.信号的基本概念1.1中断1.1.1 软中断1.1.2硬中断 1.2异步1.2.1异步和同步的比较 2.信号的主要用途3.信号的特点4.查看信号4.1Core和Term的区别4.2生成Core文件 5.初识捕捉信号5.1signal函数 6.产生信号的方式6.1.通过终端按键产生信号6.2.调用系统函数向进程发…

国内智能搜索工具实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

分享10类正规的网上赚钱平台,让你摆脱单一收入

在这个互联网飞速发展的时代&#xff0c;你是否还在为单一的收入来源而焦虑&#xff1f;别担心&#xff0c;今天带你解锁10种网上赚钱的新姿势&#xff0c;让你的收入不再单一&#xff0c;甚至可能翻倍&#xff01; 1. 文库类&#xff1a;知识的变现 你知道吗&#xff1f;你的…

k8s 数据流向 与 核心概念详细介绍

目录 一 k8s 数据流向 1&#xff0c;超级详细版 2&#xff0c;核心主键及含义 3&#xff0c;K8S 创建Pod 流程 4&#xff0c;用户访问流程 二 Kubernetes 核心概念 1&#xff0c;Pod 1.1 Pod 是什么 1.2 pod 与容器的关系 1.3 pod中容器 的通信 2&#xff0c; …

imx91的uboot编译

一、准备操作 下载半导体厂家的uboot源码 如这里我要下载的是imx91的恩智浦linux芯片bootloader 进入半导体厂家官网 下载源码&#xff0c;略 更新linux源&#xff0c;这里我是替换成清华源 vi /etc/apt/sources.list deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ fo…

【江科大STM32学习笔记】新建工程

1.建立工程文件夹&#xff0c;Keil中新建工程&#xff0c;选择型号 2.工程文件夹里建立Start、Library、User等文件夹&#xff0c;复制固件库里面的文件到工程文件夹 为添加工程文件准备&#xff0c;建文件夹是因为文件比较多需要分类管理&#xff0c;需要用到的文件一定要复…

Web UI自动化测试--PO模式

没有PO实现的测试用例的问题: 重用性低:登录功能重复可维护性差:数据和代码混合可读性差:元素定位方法杂乱(id、xpath、css混杂)可读性差:不易识别操作的含义(特别是css和xpath语法)可维护性差:如果某个元素的属性改了,你要更改多次PO(Page Object Model)页面对象模型…

完全背包问题(c++)

完全背包问题 当前有 N 种物品&#xff0c;第 i 种物品的体积是 ci​&#xff0c;价值是 wi​。 每种物品的数量都是无限的&#xff0c;可以选择任意数量放入背包。 现有容量为 V 的背包&#xff0c;请你放入若干物品&#xff0c;使总体积不超过 V&#xff0c;并且总价值尽可…