02 SpringBoot实战 -微头条之用户模块功能(第一次登录根据账号密码生成token+后续登录根据token获取用户信息+)

1 用户模块

1.1 jwt和token

1.1.1 token介绍

令牌(Token):在计算机领域,令牌是一种代表某种访问权限或身份认证信息的令牌。它可以是一串随机生成的字符或数字,用于验证用户的身份或授权用户对特定资源的访问。普通的令牌可能以各种形式出现,如访问令牌、身份令牌、刷新令牌等。简单理解 : 每个用户生成的唯一字符串标识 , 可以进行用户识别和校验优势: token验证标识无法直接识别用户的信息,盗取token后也无法`登录`程序! 相对安全!

1.1.2 jwt介绍

Token是一项规范和标准(接口)JWT(JSON Web Token)是具体可以生成,校验,解析等动作Token的技术(实现类)

1.1.3 jwt工作流程

  • 用户提供其凭据(通常是用户名和密码)进行身份验证。
  • 服务器对这些凭据进行验证,并在验证成功后创建一个JWT。
  • 服务器将JWT发送给客户端,并客户端在后续的请求中将JWT附加在请求头或参数中。
  • 服务器接收到请求后,验证JWT的签名和有效性,并根据JWT中的声明进行身份验证和授权操作
    - 在这里插入图片描述

1.1.4 jwt数据组成和包含信息

JWT由三部分组成: header(头部).payload(载荷).signature(签名)

我们需要理解的是, jwt可以携带很多信息! 一般情况,需要加入:有效时间,签名秘钥,其他用户标识信息!

有效时间的作用 : 保证token的时效性,过期可以重新登录获取!

签名秘钥的作用 : 防止其他人随意解析和校验token数据!

用户信息的作用 : 系统解析的时候,分辨Token对应的具体用户!

1.1.5 jwt使用和测试

  1. 导入依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version>
</dependency>
  1. 编写配置application.yaml
#jwt配置
jwt:token:tokenExpiration: 120 #有效时间,单位分钟tokenSignKey: headline123456  #当前程序签名秘钥 自定义
  1. 封装jwt技术工具类
    分析 : 从逻辑上讲,该工具类必须有如下功能
    a. 根据传入的用户id生成token并返回 ,以便用户免密登录
    b. 根据传入的token判断用户id , 以便知道登录的是哪个用户
    c. 判断传入的token是否还在有效期
package com.sunsplanter.utils;import com.alibaba.druid.util.StringUtils;
import io.jsonwebtoken.*;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;import java.util.Date;@Data
@Component
//读取配置文件中所有前缀为jwt.token的属性,只要最后后缀一样就自动注入
@ConfigurationProperties(prefix = "jwt.token")
public class JwtHelper {private  long tokenExpiration; //有效时间,单位毫秒 1000毫秒 == 1秒private  String tokenSignKey;  //当前程序签名秘钥//生成token字符串public  String createToken(Long userId) {System.out.println("tokenExpiration = " + tokenExpiration);System.out.println("tokenSignKey = " + tokenSignKey);String token = Jwts.builder().setSubject("YYGH-USER").setExpiration(new Date(System.currentTimeMillis() + tokenExpiration*1000*60)) //单位分钟.claim("userId", userId).signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();return token;}//从token字符串获取useridpublic  Long getUserId(String token) {if(StringUtils.isEmpty(token)) return null;Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();Integer userId = (Integer)claims.get("userId");return userId.longValue();}//判断token是否有效public  boolean isExpiration(String token){try {boolean isExpire = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getExpiration().before(new Date());//没有过期,有效,返回falsereturn isExpire;}catch(Exception e) {//过期出现异常,返回truereturn true;}}
}
4. 使用和测试
package com.sunsplanter.test;import com.sunsplanter.utils.JwtHelper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class SBTest {@Autowiredprivate JwtHelper jwtHelper;@Testpublic void test(){//生成 传入用户标识String token = jwtHelper.createToken(1L);System.out.println("token = " + token);//解析用户标识int userId = jwtHelper.getUserId(token).intValue();System.out.println("userId = " + userId);//校验是否到期! false 未到期 true到期boolean expiration = jwtHelper.isExpiration(token);System.out.println("expiration = " + expiration);}}

1.2 登录

  1. 需求描述

    用户在客户端输入用户名密码并向后端提交,后端根据用户名和密码判断登录是否成功,用户有误或者密码有误响应不同的提示信息!

  2. 接口描述

    url地址: user/login

    请求方式:POST

    请求参数:

{"username":"zhangsan", //用户名"userPwd":"123456"     //明文密码
}

响应数据:

成功

{"code":"200",         // 成功状态码 "message":"success"   // 成功状态描述"data":{"token":"... ..." // 根据用户id的token}
}

失败

{"code":"501","message":"用户名有误""data":{}
}
{"code":"503","message":"密码有误""data":{}
}
  1. 实现代码
    1. controller
@RestController
@RequestMapping("user")
//解决跨域访问问题
@CrossOrigin
public class UserController {@Autowiredprivate UserService userService;@PostMapping("login")public Result login(@RequestBody User user){Result result = userService.login(user);System.out.println("result = " + result);return result;}}
  1. service
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>implements UserService{@Autowiredprivate JwtHelper jwtHelper;@Autowiredprivate  UserMapper userMapper;/*** 登录业务实现* @param user* @return result封装'* * 大概流程:*    1. 账号进行数据库查询 返回用户对象*    2. 对比用户密码(md5加密)*    3. 成功,根据userId生成token -> map key=token value=token值 - result封装*    4. 失败,判断账号还是密码错误,封装对应的枚举错误即可* * 登录需求* 地址: /user/login* 方式: post* 参数:*    {*     "username":"zhangsan", //用户名*     "userPwd":"123456"     //明文密码*    }* 返回:*   {*    "code":"200",         // 成功状态码*    "message":"success"   // 成功状态描述*    "data":{*         "token":"... ..." // 用户id的token*     }*  }*/@Overridepublic Result login(User user) {//根据账号查询//创建一个条件构造器对象,并将等于条件封装入内(数据库中查找username值与传入user.username值一样的记录)LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(User::getUsername,user.getUsername());User loginUser = userMapper.selectOne(queryWrapper);//账号判断if (loginUser == null) {//账号错误return Result.build(null, ResultCodeEnum.USERNAME_ERROR);}//判断密码if (!StringUtils.isEmpty(user.getUserPwd())&& loginUser.getUserPwd().equals(MD5Util.encrypt(user.getUserPwd()))){//账号密码正确//根据用户唯一标识生成tokenString token = jwtHelper.createToken(Long.valueOf(loginUser.getUid()));Map data = new HashMap();data.put("token",token);return Result.ok(data);}//密码错误return Result.build(null,ResultCodeEnum.PASSWORD_ERROR);}
}

在idea中模拟发送Json数据,可以得到响应 , 返回一个token.
在这里插入图片描述
在这里插入图片描述

1.3 根据token获取用户信息

  1. 需求 : 第一次登录以后 , 客户一段时间内都不用再输入账号密码就能登录了 . 实现的原理就是 , 客户端发送请求头中包含token , 后端可以根据token获取登录用户的详细信息. 本次要求后端获取用户信息(密码除外)后返回给前端展示.

  2. 接口描述

    url地址:user/getUserInfo

    请求方式:GET

    请求头:token: token内容

    响应数据:

    成功

{"code": 200,"message": "success","data": {"loginUser": {"uid": 1,"username": "zhangsan","userPwd": "","nickName": "张三"}}
}
失败
{"code": 504,"message": "notLogin","data": null
}
  1. 代码编写
    userController 新增:
    @GetMapping("getUserInfo")//RequstHeader注解提取请求头public Result userInfo(@RequestHeader String token){Result result = userService.getUserInfo(token);return result;}

userService新增:

	    Result getUserInfo(String token);

userServiceImpl新增:

    /*** 大概流程:*    1.获取token,解析token对应的userId*    2.根据userId,查询用户数据*    3.将用户数据的密码置空,并且把用户数据封装到结果中key = loginUser*    4.失败返回504 (本次先写到当前业务,后期提取到拦截器和全局异常处理器)*/@Overridepublic Result getUserInfo(String token) {//判断是否过期,boolean expiration = jwtHelper.isExpiration(token);//若失效,返回响应码if (expiration) {return Result.build(null,ResultCodeEnum.NOTLOGIN);} else {int userId = jwtHelper.getUserId(token).intValue();User user = userMapper.selectById(userId);user.setUserPwd("");Map data = new HashMap();data.put("loginUser",user);return Result.ok(data);}}

在这里插入图片描述

1.4 1. 用户注册时检查用户名是否已被占用

  1. 需求描述 : 用户在注册时输入用户名时,立刻将用户名发送给后端,后端根据用户名查询用户名是否可用(是否被占用)并做出响应

  2. 接口描述

    url地址:user/checkUserName

    请求方式:POST

    请求参数:param形式
    username=zhangsan

响应数据:

成功

{"code":"200","message":"success""data":{}
}
失败
{"code":"505","message":"用户名占用""data":{}
}
  1. 代码编写
    userController 新增:

userService新增:

	  

userServiceImpl新增:

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

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

相关文章

找不到mfc140u.dll,无法继续执行代码要怎么去解决?

当你尝试运行某些程序或游戏时&#xff0c;可能会遇到“msvcr110.dll丢失”的错误提示。这个错误通常表示你的系统缺少了msvcr110.dll文件&#xff0c;而这个文件是Microsoft Visual C 2012 Redistributable的一部分。在本文中&#xff0c;我们将介绍msvcr110.dll丢失的解决方法…

自定义注解与拦截器实现不规范sql拦截(自定义注解填充插件篇)

在自定义注解与拦截器实现不规范sql拦截&#xff08;拦截器实现篇&#xff09;中提到过&#xff0c;写了一个idea插件来辅助对Mapper接口中的方法添加自定义注解&#xff0c;这边记录一下插件的实现。 需求简介 在上一篇中&#xff0c;定义了一个自定义注解对需要经过where判…

【剑指offer】重建二叉树

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述1、题目2、示例 二、题目分析1、递归2、栈 一、题目描述 1、题目 剑指offer&#xff1a;重建二叉树 给定节…

[C++]:12:模拟实现list

[C]:12:模拟实现list 一.看一看SGI的stl_list的源码&#xff1a;1.基础结构构造函数1.节点结构&#xff1a;2.节点构造函数&#xff1a;3.链表结构&#xff1a;4.链表的构造函数&#xff1a; 2.析构1.节点析构&#xff1a;2.链表的析构&#xff1a; 3.迭代器 二.模拟实现list1.…

vue+elementUI el-select 中 没有加clearable出现一个或者多个×清除图标问题

1、现象&#xff1a;下方截图多清除图标了 2、在全局common.scss文件中加一个下方的全局样式noClear 3、在多清除图标的组件上层div加noClear样式 4、清除图标去除成功

基于扩散模型语音驱动人物头像说话模型:DreamTalk

1 DreamTalk介绍 DreamTalk&#xff1a;由清华大学、阿里巴巴和华中科大共同开发的一个基于扩散模型让人物头像说话的框架。 能够根据音频让人物头像照片说话、唱歌并保持嘴唇的同步和模仿表情变化。这一框架具有以下特点: DreamTalk能够生成高质量的动画&#xff0c;使人物脸…

【操作系统】实验一 Linux操作系统安装

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

Nginx的access_log 状态码499的问题排查

前提&#xff1a;公司的项目网站&#xff0c;运行环境是lnmp环境下 一、起因 如下图&#xff0c;网站请求超过60s(如&#xff1a;导出半年的报表数据到excel)时&#xff0c;报如下错误&#xff0c;且浏览器上没有返回值 二、发展 查找nginx和php-fpm都没有报错日志。于是先把…

C++中命名空间、缺省参数、函数重载

目录 1.命名空间 2.缺省参数 3.函数重载 1.命名空间 在C中定义命名空间我们需要用到namespace关键字&#xff0c;后面跟上命名空间的名字&#xff0c;结构框架有点类似结构体&#xff08;如图所示&#xff09; 上面的代码我一一进行讲解&#xff1a; 1.我们先来说第三行和main函…

MySql必知必会

11.什么是自适应哈希索引&#xff1f; 自适应Hash索引&#xff08;Adatptive Hash Index&#xff0c;内部简称AHI&#xff09;是InnoDB的三大特性之一&#xff0c;还有两个是 Buffer Pool简称BP、双写缓冲区&#xff08;Doublewrite Buffer&#xff09;。 1、自适应即我们不需…

网络防御保护1

网络防御保护 第一章 网络安全概述 网络安全&#xff08;Cyber Security&#xff09;是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然的或者恶意的原因而遭受到破坏、更改、泄露&#xff0c;系统连续可靠正常地运行&#xff0c;网络服务不中断 随着数…

今年想考CISP的一定要看完❗️

&#x1f3af;国家注册信息安全专业人员&#xff08;英文名称Certified Information Security Professional&#xff0c;简称“CISP"&#xff09;&#xff0c;是由中国信息安全测评中心于2002年推出的、业内公认的国内信息安全领域zqw的gj级认证&#xff0c;是国家对信息安…