当前位置: 首页 > news >正文

东莞高埗网站建设/百度seo正规优化

东莞高埗网站建设,百度seo正规优化,英文网站建设多少钱,企业管理公司的经营范围6.4 关于登录 最简单的登录: 1、web登录页填写登录信息,前端发送登录信息到后端; 2、后端接受登录信息,并校验。校验成功,返回成功结果。 这种登录会出现一个问题,用户1成功登录之后,获取到后台…

6.4 关于登录

最简单的登录:

        1、web登录页填写登录信息,前端发送登录信息到后端;

        2、后端接受登录信息,并校验。校验成功,返回成功结果。

        这种登录会出现一个问题,用户1成功登录之后,获取到后台管理页,将这个页面的url分享给用户2,用户2没有进行登录就会直接进入到后台管理页,容易造成信息泄露;

        解决方法:用户在进入后台管理页之前要进行校验;

几种常见的登录验证的方式:

方式1、cookie-session

1、用户带登录的时候,就会把用户信息发送到后端,后端根据用户信息创建一个sessionid,将用户登录的相关信息放入到session中,后续通过sessionid来进行查找校验,并将sessionid传送到前端;

2、前端接收到sieeionid之后将其存入到cookie中,后续在进行登陆之后会携带cookie,后端会根据前端发送过来的cookie解析到其中的sieeionid,通过sessionid来查找是否用这个id所对应的用户消息。如果存在用户信息,则表示之前这个用户登录过,就会放心该用户跳转到其他界面;如果该id没有查找到相关的用户信息,则表示该用户之前没有进行登录过,不会放行;

缺点:1、cookie只在web网页中生成,存在环境限制;

        2、这种方式不能跨域;

        3、cookie只能在本机保存,不能在集群环境中使用;

方式2: token认证

        上图的token是存储在redis,由于redis是可以部署在集群环境中,所以解决了cookie-session的一下缺陷;

        缺点:用户数量大会导致频繁的访问redis校验token,对于内存来说有很大的压力。

方式三:基于token的jwt令牌认证

 

        1、前端的登录信息发送到后端之后,后端基于jwt服务产生一个string类型的字符串,成为jwt令牌,这个令牌是不需要存储在后端的,而是直接返回到前端;

        2、前端使用本地的存储方式,将jwt存储起来,后续在进行操作的话会带着jwt令牌到后端,后端会对jwt令牌进行校验,如果能够正确使用jwt解密,说明校验通过了;

        jwt:实际上是一个加解密的过程,这个过程是依靠jwt独立的工具包来完成和实现的。

        jwt:结构是由负载,签名和头部组成的,由这三部分组成一个串;

6.5 jwt令牌工具类的实现

        该工具类主要完成jwt的加密和解密操作:

 首先引入相关的依赖:

新建jwtutil类:

public class JWTUtil {private static final Logger logger = LoggerFactory.getLogger(JWTUtil.class);/*** 密钥:Base64编码的密钥*/private static final String SECRET = "weS2l8Tp9wDFov9ic72l/9VRT3j9aYfhEfi8qwGMDgU=";/*** 生成安全密钥:将一个Base64编码的密钥解码并创建一个HMAC SHA密钥。*/private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET));/*** 过期时间(单位: 毫秒)*/private static final long EXPIRATION = 60*60*1000*24*30;//一个月/*** 生成密钥** @param claim  {"id": 12, "name":"张山"}* @return*/public static String genJwt(Map<String, Object> claim){//签名算法String jwt = Jwts.builder().setClaims(claim)             // 自定义内容(载荷).setIssuedAt(new Date())      // 设置签发时间.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)) // 设置过期时间.signWith(SECRET_KEY)         // 签名算法,和加解密相关.compact();return jwt;}/*** 验证密钥*/
//    Claims是jwt里面定义的对象public static Claims parseJWT(String jwt){if (!StringUtils.hasLength(jwt)){return null;}// 创建解析器, 设置签名密钥JwtParserBuilder jwtParserBuilder = Jwts.parserBuilder().setSigningKey(SECRET_KEY);Claims claims = null;try {//解析tokenclaims = jwtParserBuilder.build().parseClaimsJws(jwt).getBody();}catch (ExpiredJwtException e){// 签名验证失败
//            logger.error("解析令牌错误,jwt:{}", jwt, e);claims = e.getClaims();}return claims;}/*** 从token中获取用户ID*/public static Integer getUserIdFromToken(String jwtToken) {Claims claims = JWTUtil.parseJWT(jwtToken);if (claims != null) {Map<String, Object> userInfo = new HashMap<>(claims);return (Integer) userInfo.get("userId");}return null;}
}

controller层登录接口设计:

    @RequestMapping("/password/login")public CommonResult<UserLoginResult> userPasswordLogin(@Validated @RequestBody UserPasswordLoginParam param) {logger.info("userPasswordLogin UserPasswordLoginParam:{}",JacksonUtil.writeValueAsString(param));UserLoginDTO userLoginDTO = userService.login(param);return CommonResult.success(convertToUserLoginResult(userLoginDTO));}

 service层登录接口实现:

@Overridepublic UserLoginDTO login(UserLoginParam param) {UserLoginDTO userLoginDTO;// 类型检查与类型转换,java 14及以上版本if (param instanceof UserPasswordLoginParam loginParam) {// 密码登录流程userLoginDTO = loginByUserPassword(loginParam);} else if (param instanceof ShortMessageLoginParam loginParam) {// 短信验证码登录流程userLoginDTO = loginByShortMessage(loginParam);} else {throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);}return userLoginDTO;}private UserLoginDTO loginByShortMessage(ShortMessageLoginParam loginParam) {if (!RegexUtil.checkMobile(loginParam.getLoginMobile())) {throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);}// 获取用户数据UserDO userDO = userMapper.selectByPhoneNumber(new Encrypt(loginParam.getLoginMobile()));if (userDO == null) {throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);} else if (StringUtils.hasText(loginParam.getMandatoryIdentity())&& !loginParam.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())) {throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);}// 校验验证码String code = verificationCodeService.getVerificationCode(loginParam.getLoginMobile());if (!loginParam.getVerificationCode().equals(code)) {throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);}// 塞入返回值(JWT)Map<String, Object> claim = new HashMap<>();claim.put("id", userDO.getId());claim.put("identity", userDO.getIdentity());String token = JWTUtil.genJwt(claim);UserLoginDTO userLoginDTO = new UserLoginDTO();userLoginDTO.setToken(token);userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));return userLoginDTO;}private UserLoginDTO loginByUserPassword(UserPasswordLoginParam loginParam) {UserDO userDO = null;// 判断手机登录还是邮箱登录if (RegexUtil.checkMail(loginParam.getLoginName())) {// 邮箱登录// 根据邮箱查询用户表userDO = userMapper.selectByMail(loginParam.getLoginName());} else if (RegexUtil.checkMobile(loginParam.getLoginName())) {// 手机号登录// 根据手机号查询用户表userDO = userMapper.selectByPhoneNumber(new Encrypt(loginParam.getLoginName()));} else {throw new ServiceException(ServiceErrorCodeConstants.LOGIN_NOT_EXIST);}// 校验登录信息if (null == userDO) {throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);} else if (StringUtils.hasText(loginParam.getMandatoryIdentity())&& !loginParam.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())) {// 强制身份登录,身份校验不通过throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);} else if (!DigestUtil.sha256Hex(loginParam.getPassword()).equals(userDO.getPassword())) {// 校验密码不同throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);}// 塞入返回值(JWT)Map<String, Object> claim = new HashMap<>();claim.put("id", userDO.getId());claim.put("identity", userDO.getIdentity());String token = JWTUtil.genJwt(claim);UserLoginDTO userLoginDTO = new UserLoginDTO();userLoginDTO.setToken(token);userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));return userLoginDTO;}

使用postman对登录进行测试:

账号密码:

验证码登录:

 开启redis缓存验证码:service redis-server start

发送验证码:

验证码登录:

6.6 前端登录完善

进行前端测试:

密码登录:

短信验证码登录:

登录成功之后进入新的界面:

在登录页面点击注册进入注册见面,注册成功之后返回登录界面:

6.7 登录拦截器

        在设置好jwt令牌登陆之后,用户进行登录操作,会得到后端传过来的jwt令牌,其次用户会拿着这个令牌去访问其他界面的时候,后端会对这个jwt令牌进行校验,这里采用的是拦截器,当然不是所有的请求都需要校验,会进行相关配置;

登录拦截器:

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {/**登录拦截器* 预处理,业务请求之前调用* @param request* @param response* @param handler* @return*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 获取请求头,jwt是在request的请求头中的String token = request.getHeader("user_token");log.info("获取token:{}", token);log.info("获取路径:{}", request.getRequestURI());// 令牌解析Claims claims = JWTUtil.parseJWT(token);if (claims == null) {log.error("解析JWT令牌失败!");response.setStatus(401);return false;}log.info("解析JWT令牌成功!放行");return true;}
}

配置登录拦截资源:

@Configuration
public class AppConfig implements WebMvcConfigurer {//配置项@Autowiredprivate LoginInterceptor loginInterceptor;private final List<String> excludes = Arrays.asList("/**/*.html","/css/**","/js/**","/pic/**","/*.jpg","/*.png","/favicon.ico","/**/login","/register","/verification-code/send");@Override//添加自定义的登录拦截器public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludes);}
}

ps:关于登录的内容就到这里了,谢谢观看!!!

相关文章:

java抽奖系统登录下(四)

6.4 关于登录 最简单的登录&#xff1a; 1、web登录页填写登录信息&#xff0c;前端发送登录信息到后端&#xff1b; 2、后端接受登录信息&#xff0c;并校验。校验成功&#xff0c;返回成功结果。 这种登录会出现一个问题&#xff0c;用户1成功登录之后&#xff0c;获取到后台…...

解决阿里云轻量级服务器 Ubuntu 24.04.1 LTS 没网也 ping 不通 8.8.8.8 以及 route -n 没有输出任何转发信息

事情发生在两天前&#xff0c;位于公网的阿里云轻量级服务器&#xff08;Ubuntu 24.04.1 LTS&#xff09;忽然没网。主要是上次上服务器进行配置已经是一个多月前&#xff0c;最近也没有做什么事情&#xff0c;就忽然没网了&#xff0c;让人纳闷。更主要的是&#xff0c;上次备…...

跨域问题及其解决方案

跨域问题及其解决方案 在Web开发中&#xff0c;跨域问题是一个常见的安全限制&#xff0c;它涉及到浏览器的同源策略&#xff08;Same-Origin Policy&#xff09;。本文将详细解释跨域问题的原因、影响以及几种常见的解决方案&#xff0c;并提供在Java中的实现方法。 目录 跨…...

在CentOS中安装和卸载mysql

在CentOS7中安装和卸载mysql 卸载mysql1、查看是否安装过mysql2、查看mysql服务状态3、关闭mysql服务4、卸载mysql相关的rpm程序5、删除mysql相关的文件6、删除mysql的配置文件my.cnf 安装mysql1、下载mysql相关的rpm程序2、检查/tmp临时目录权限3、安装mysql前的依赖检查3、安…...

React简单入门 - [Next.js项目] - 页面跳转、AntD组件、二级目录等

须知 1Next.js 官网(英文)https://nextjs.org/2Next.js 文档(中文)https://nextjscn.org/docs/3Ant Design组件总览https://ant-design.antgroup.com/components/overview-cn4tailwindcss类名大全 官网https://www.tailwindcss.cn/docs/justify-content 5tailwindcss常用类…...

Redis安装和Python练习(Windows11 + Python3.X + Pycharm社区版)

环境 Windows11 Python3.X Pycharm社区版 思路 1 github下载redis压缩包 &#xff0c;安装并启动redis服务&#xff0c;在客户端连接redis服务。 2 在pycharm中运行python程序&#xff0c;连接redis服务&#xff0c;熟悉redis的使用和巩固python语言。 3 python开发环境…...

Sqoop脚本编写(Mysql---->>hdfs)

目录 语法手册编写方式脚本文件类型文件编写.jar路径指定 执行效果执行方式效果 语法手册 参考博客 编写方式 脚本文件类型 只要是可读的文件即可&#xff08;.txt或者.sh等其他类型&#xff0c;不带文件后缀也可以&#xff0c;但二进制文件最好不要&#xff09; 文件编写…...

帝可得项目redis连接不上

首先我一切配置都没问题&#xff1a; 1. redis-server启动 2. 可视化界面显示redis已连接 原因&#xff1a; 不知道是不是因为不同版本的问题(因为我之前的sky就没这个问题) 这里把password改成auth就可以了...

JS中this的值详细讲解以及面试指向练习

this 的值取决于它出现的上下文&#xff1a;函数、类或全局。 在函数内部&#xff0c;this 的值取决于函数如何被调用&#xff0c;this 是语言在函数体被执行时为你创建的绑定 对于典型的函数&#xff0c;this 的值是函数被访问的对象。换句话说&#xff0c;如果函数调用的形…...

显示浮动式窗口的方法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了AlertDialog Widget相关的内容,本章回中将介绍BottomSheet Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的BottomSheet是一种弹出式窗口,和上一章回中介绍的AlertDialog类似,但是也…...

FireFox火狐浏览器企业策略禁止更新

一直在用火狐浏览器&#xff0c;但是经常提示更新&#xff0c;进入浏览器右上角就弹出提示&#xff0c;比较烦。多方寻找&#xff0c;一直没有找到合适的方案&#xff0c;毕竟官方没有给出禁用检查更新的选项&#xff0c;甚至about:config里都没有。 最终找到了通过企业策略控…...

C++类的运算符重载

目标 让自定义的类直接使用运算符运算 代码 头文件及类定义 #include <iostream>using namespace std; class Complex {int rel;int vir; public:void show(){cout <<"("<<this->rel<<","<<this->vir<<&quo…...

泷羽Sec学习笔记-zmap搭建炮台

zmap搭建炮台 zmap扫描环境&#xff1a;kali-linux 先更新软件库 sudo apt update 下载zmap sudo apt install zmap 开始扫描(需要root权限) sudo zmap -p 80 -o raw_ips.txt 代码解析&#xff1a; sudo&#xff1a;以超级用户&#xff08;管理员&#xff09;权限运行…...

分析M0G突破后急剧下跌内因,x.game阐述不利面延续多久

MOG最新消息显示&#xff0c;美国唐纳德-的一则声明公开表示支持一种基于以太坊网络ERC-20代币标准的病毒式meme代币——Mog Coin&#xff08;MOG&#xff09;&#xff0c;这一消息迅速发酵。然而&#xff0c;令人意想不到的是&#xff0c;在这位全球知名政治人物的背书之后&am…...

网络爬虫全解析

一、网络爬虫基础要点 &#xff08;一&#xff09;爬虫原理 目标确定&#xff1a;明确需要抓取数据的网站或网页范围&#xff0c;例如针对特定电商平台抓取商品信息&#xff0c;或聚焦新闻网站获取新闻报道内容&#xff0c;要考量数据的价值与用途。URL 解析&#xff1a;理解网…...

《孤岛惊魂4》无法启动提示缺少“msvcp100.dll”快速修复方法!

《孤岛惊魂4》缺少msvcp100.dll的解决之道 在探索《孤岛惊魂4》这款充满惊险与刺激的射击游戏时&#xff0c;玩家可能会遇到一些意外的障碍&#xff0c;其中之一便是“缺少msvcp100.dll”的错误提示。这个错误不仅让游戏无法正常启动&#xff0c;还可能让玩家对游戏的热情大打…...

GS-SLAM论文阅读--RGBDS-SLAM

前言 最近GS-SLAM领域的工作层出不穷&#xff0c;有很多不错的工作出现。接下来慢慢写一下相关博客。 文章目录 前言1.背景介绍2.关键内容2.1 3D多层次金字塔高斯喷溅2.2 紧密耦合多特征重构优化2.3总体流程 3.文章贡献4.个人思考 1.背景介绍 高保真重建是密集SLAM的关键。最…...

条件编译->enable_if和 if constexpr使用区别

enable_if 和 if constexpr 是 C 中用于控制编译或运行时条件的重要工具&#xff0c;它们各有不同的用途和使用场景。以下是它们的主要区别&#xff1a; 1. enable_if std::enable_if 是一个类型特征&#xff0c;用于在编译时根据条件选择类型。常用于模板元编程&#xff0c;…...

介绍一下CSS中伪类和伪元素的概念

一、伪类&#xff08;Pseudo - Classes&#xff09; 1. 定义 伪类是添加到选择器的关键字&#xff0c;用于定义元素的特殊状态。这些状态不是由文档树中的结构或属性来表示&#xff0c;而是基于用户行为&#xff08;如鼠标悬停&#xff09;、元素状态&#xff08;如被选中&am…...

【橘子ES】熔断器Circuit breaker

一、相关概念 我们在日常的开发中&#xff0c;关于服务之间的熔断操作似乎很常见&#xff0c;当请求超过了我们服务所认为可以承受的一个上限阈值的时候&#xff0c;我们为了保护服务不会被进一步的高负载压崩溃&#xff0c;我们有时候会选择熔断请求&#xff0c;此时服务不再…...

6.4 CPU性能分析--Intel处理器跟踪技术

Intel处理器跟踪PT技术是记录程序执行过程的技术&#xff0c;它把记录信息编码报文存到高压缩率的二进制文件中。该二进制文件结合每条指令的时间戳重建执行流。PT技术覆盖度大&#xff0c;开销小&#xff0c;有关开销的信息详见&#xff0c;主要用于性能问题的事后分析和根因定…...

期权懂|如何用第三方平台开通期权?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何用第三方平台开通期权&#xff1f; 如果不能满足常规的期权开户条件&#xff0c;可以考虑以下几种方法来尝试开户&#xff1a; 一、选择第三方平台&#xff1a; 通过网络搜…...

JS中const有没有变量提升

在JavaScript中&#xff0c;const 关键字用于声明一个只读的常量&#xff0c;其值在初始化后不能被重新赋值。关于变量提升&#xff08;Hoisting&#xff09;&#xff0c;它是JavaScript中一个重要的概念&#xff0c;指的是无论变量或函数声明在何处&#xff0c;它们都会被“提…...

Axure RP全面介绍:功能、应用与中文替代方案

Axure RP是一款功能强大的原型设计工具&#xff0c;它被广泛应用于网页和移动应用的设计领域。Axure RP集成了设计、原型制作和文档管理&#xff0c;为产品管理人员、设计师和开发人员提供了一个综合的平台。让我们一步步了解Axure的基本功能、使用技巧以及中文支持平台——“在…...

WordPress用户首次登录强制修改密码

有些企业网站要求很高&#xff0c;比如用户首次登录强制要求修改密码&#xff0c;这里提供一段代码&#xff0c;用于实现强制修改密码供参考。 通过代码可以实现&#xff0c;用户正常注册或者管理员在后台添加用户时&#xff0c;会添加首次登录标记&#xff0c;用户首次登录后会…...

AI开源南京分享会回顾录

AI 开源南京分享会&#xff0c;已于2024年11月30日下午在国浩律师&#xff08;南京&#xff09;事务所5楼会议厅成功举办。此次活动由 KCC南京、PowerData、RISC-Verse 联合主办&#xff0c;国浩律师&#xff08;南京&#xff09;事务所协办。 活动以“开源视角的 AI 对话”为主…...

基于事件驱动的websocket简单实现

websocket的实现 什么是websocket&#xff1f; WebSocket 是一种网络通信协议&#xff0c;旨在为客户端和服务器之间提供全双工、实时的通信通道。它是在 HTML5 规范中引入的&#xff0c;可以让浏览器与服务器进行持久化连接&#xff0c;以便实现低延迟的数据交换。 WebSock…...

【leetcode100】反转链表

1、题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 2、初始思路 2.1 思路 # Definition for singly-linked list. # class ListNode: # …...

禅道Bug的一次迁移

一、场景 平时工作记录在公司禅道上的问题想备份一份到本地&#xff0c;但是又没有公司禅道的数据库信息&#xff0c;有时候出测试报告想批量调整数据方便截图很困难&#xff0c;同时也为了学习禅道数据流转过程&#xff0c;所以有了把缺陷保存到本地一份的想法。 实际上禅道支…...

c段和旁站讲解(附查询网址)

1. C段&#xff08;C类子网段&#xff09; C段就是一个IP地址的小范围。比如&#xff0c;假设你有一个家庭Wi-Fi网络&#xff0c;Wi-Fi会分配给你一组IP地址&#xff08;每个设备一个IP地址&#xff09;。如果你的网络分配的是类似 192.168.1.0 这样的IP地址&#xff0c;那么这…...