尚医通-登录注册搭建-JWT(二十八)

news2024/11/16 16:33:29

目录:

(1)前台用户系统-登录注册-需求分析

(2)前台用户系统-登录注册-搭建环境

(3)前台用户系统-手机登录-基本实现

(4)前台用户系统-手机登录-整合JWT


(1)前台用户系统-登录注册-需求分析

点击某一个科室,可以看到科室中号员的信息,排班信息,可以进行相关的挂号,在挂号之前需要进行登录,要知道谁去挂号,这个人的信息,最终进行相关的支付

 在点击科室之前需要判断是否登录,没有登录,弹出登录框进行登录,点击有右上角的登录按钮,进行弹出框登录

  1. 登录效果

  1. 登录需求
  1. 登录采取弹出层的形式
  2. 登录方式:
  1. 手机号码+手机验证码
  2. 微信扫描
  1. 无注册界面,第一次登录根据手机号判断系统是否存在,如果不存在则自动注册
  2. 微信扫描登录成功必须绑定手机号码,即:第一次扫描成功后绑定手机号,以后登录扫描直接登录成功
  3. 网关统一判断登录状态(还可以用Session做判断),如何需要登录,页面弹出登录层

(2)前台用户系统-登录注册-搭建环境

在service-user模块中进行开发:首先先创建配置文件:

 

 

# 服务端口
server.port=8203
# 服务名
spring.application.name=service-user

# 环境设置:dev、test、prod
spring.profiles.active=dev

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yygh_user?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root123

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/user/mapper/xml/*.xml

创建启动类:

package com.atguigu.yygh.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.atguigu")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.atguigu")
public class ServiceUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceUserApplication.class, args);
    }
}

配置网关:

在网关模块中添加:新的路由

 

 

 实体类已经在model模块中引入了:

package com.atguigu.yygh.model.user;

import com.atguigu.yygh.model.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * <p>
 * UserInfo
 * </p>
 *
 * @author qy
 */
@Data
@ApiModel(description = "UserInfo")
@TableName("user_info")
public class UserInfo extends BaseEntity {
	
	private static final long serialVersionUID = 1L;
	
	@ApiModelProperty(value = "微信openid")
	@TableField("openid")
	private String openid;

	@ApiModelProperty(value = "昵称")
	@TableField("nick_name")
	private String nickName;

	@ApiModelProperty(value = "手机号")
	@TableField("phone")
	private String phone;

	@ApiModelProperty(value = "用户姓名")
	@TableField("name")
	private String name;

	@ApiModelProperty(value = "证件类型")
	@TableField("certificates_type")
	private String certificatesType;

	@ApiModelProperty(value = "证件编号")
	@TableField("certificates_no")
	private String certificatesNo;

	@ApiModelProperty(value = "证件路径")
	@TableField("certificates_url")
	private String certificatesUrl;

	@ApiModelProperty(value = "认证状态(0:未认证 1:认证中 2:认证成功 -1:认证失败)")
	@TableField("auth_status")
	private Integer authStatus;

	@ApiModelProperty(value = "状态(0:锁定 1:正常)")
	@TableField("status")
	private Integer status;

}

 创建controller:UserInfoApiController 

package com.atguigu.yygh.user.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/user")
public class UserInfoApiController {
}

创建service:UserInfoService 

package com.atguigu.yygh.user.service;

public interface UserInfoService {
}

实现类:UserInfoService Impl:

package com.atguigu.yygh.user.service.impl;


import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.user.mapper.UserInfoMapper;
import com.atguigu.yygh.user.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class UserInfoServiceImpl extends
        ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
}

创建mapper:UserInfoMapper  

package com.atguigu.yygh.user.mapper;

import com.atguigu.yygh.model.user.UserInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserInfoMapper extends BaseMapper<UserInfo> {
}

UserInfoMapper.xml: 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.yygh.user.mapper.UserInfoMapper">

</mapper>

创建配置类:UserConfig :

package com.atguigu.yygh.user.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.atguigu.yygh.user.mapper")
public class UserConfig {
}

(3)前台用户系统-手机登录-基本实现

手机进行登录,登录的时候需要传入手机号和验证码,可以写一个vo类:

package com.atguigu.yygh.vo.user;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description="登录对象")
public class LoginVo {

    @ApiModelProperty(value = "openid")
    private String openid;

    @ApiModelProperty(value = "手机号")
    private String phone;

    @ApiModelProperty(value = "密码")
    private String code;

    @ApiModelProperty(value = "IP")
    private String ip;
}

 UserInfoApiController :

package com.atguigu.yygh.user.controller;

import com.atguigu.yygh.common.result.Result;
import com.atguigu.yygh.user.service.UserInfoService;
import com.atguigu.yygh.vo.user.LoginVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/api/user")
public class UserInfoApiController {

    @Autowired
    private UserInfoService userInfoService;


    //用户手机登录接口
    @ApiOperation(value = "用户登录")
    @PostMapping("login")
    public Result login(@RequestBody LoginVo loginVo) {

        Map<String, Object> info = userInfoService.login(loginVo);
        return Result.ok(info);
    }

}

UserInfoService: 

package com.atguigu.yygh.user.service;

import com.atguigu.yygh.vo.user.LoginVo;

import java.util.Map;

public interface UserInfoService{
    //用户手机登录接口
    Map<String, Object> login(LoginVo loginVo);
}

实现类:UserInfoServiceImpl 

package com.atguigu.yygh.user.service.impl;


import com.atguigu.yygh.common.exception.HospitalException;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.user.mapper.UserInfoMapper;
import com.atguigu.yygh.user.service.UserInfoService;
import com.atguigu.yygh.vo.user.LoginVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

@Service
public class UserInfoServiceImpl extends
        ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    //用户手机登录接口
    @Override
    public Map<String, Object> login(LoginVo loginVo) {
        //从loginVo里面获取输入的手机号和验证码
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        //校验参数 判断手机号和验证码是否为空
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) {
            throw new HospitalException(ResultCodeEnum.PARAM_ERROR);
        }

        //(整合阿里云短信服务)判断手机验证码和输入的验证码是否一致

        //判断是否是第一次登录:根据手机号查询数据库,如果不存在相同的手机号就是第一次登录
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        UserInfo userInfo = baseMapper.selectOne(queryWrapper);
        if(null == userInfo) {//等于空表示第一次使用这个手机号登录
            userInfo = new UserInfo();
            userInfo.setName("");
            userInfo.setPhone(phone);
            userInfo.setStatus(1);
            baseMapper.insert(userInfo);
        }

        //校验是否被禁用
        if(userInfo.getStatus() == 0) {//判断用户状态是否为0禁用状态
            throw new HospitalException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }


        //不是第一次登录,直接登陆

        //返回登录的信息 :返回用户名 返回tocken信息
        Map<String, Object> map = new HashMap<>();
        String name = userInfo.getName();
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getNickName();
        }
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getPhone();
        }
        map.put("name", name);
        map.put("token", "");

        return map;
    }
}

说明:

  1. 验证码先注释,后续校验
  2. 登录成功生成token,后续讲解

(4)前台用户系统-手机登录-整合JWT

 JWT工具:tocken的生成,需要按照一定的规则,规则怎么样不确定,规则可以自己约定,在开发中呢,有一种通用的工具,叫做JWT,JWT给我们约定好了一种规则,用JWT帮助我们生成这样一段token的字符串,我们采用JWT的方式来生成token的字符串

 JWT介绍

JWT工具

JWT(Json Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。

JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上

JWT最重要的作用就是对 token信息的防伪作用。由于自己定义的规则,用户可能猜到,进行伪造,JWT可以防伪:对某些字段进行加密、编码处理

JWT的原理,

一个JWT由三个部分组成:公共部分、私有部分、签名部分。最后由这三者组合进行base64编码得到JWT。

JWT:生成的tocken字符串由3部分组成:头部分,主体,签名哈希 

 

 

 

 把JWT放到common_util模块中:引入依赖

 创建工具类:

package com.atguigu.yygh.common.helper;

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import java.util.Date;

public class JwtHelper {
    private static long tokenExpiration = 24*60*60*1000;//tonken的过期时间
    private static String tokenSignKey = "123456";//token的签名秘钥 根据秘钥做一个编码,做一个签名,做一个加密

    //根基参数生成token
    public static String createToken(Long userId, String userName) {
        String token = Jwts.builder()
                .setSubject("YYGH-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))//过期时间
                .claim("userId", userId)  //主体信息
                .claim("userName", userName) //主体信息
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)//签名哈希
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }
    //根据token字符串得到用户id
    public static 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 static String getUserName(String token) {
        if(StringUtils.isEmpty(token)) return "";
        Jws<Claims> claimsJws
                = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("userName");
    }
    public static void main(String[] args) {
        String token = JwtHelper.createToken(1L, "55");
        System.out.println(token);
        System.out.println(JwtHelper.getUserId(token));
        System.out.println(JwtHelper.getUserName(token));
    }
}

 

 修改实现类上面没有写的token部分:UserInfoServiceImpl 

 使用swagger测试:

 

yygh_user数据库表user_info中的数据

 点击:

 数据库成功的加入一条信息:

 

 

 

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

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

相关文章

【JUC并发编程】使用多线程可能带来什么问题

【JUC并发编程】使用多线程可能带来什么问题? 文章目录【JUC并发编程】使用多线程可能带来什么问题?什么是多线程并发为什么会出现线程带来的安全性问题可见性问题原子性问题有序性问题活跃性问题性能问题引起线程切换的几种方式什么是多线程 多线程意味着你能够在同一个应用…

Linux的ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM及分配页释放页函数的简单介绍

Linux的ZONE_DMA&#xff0c;ZONE_NORMAL,ZONE_HIGHMEM及分配页释放页函数的简单介绍简单介绍一下页&#xff1a;Linux 区&#xff1a;分配页系统调用释放页系统调用简单介绍一下页&#xff1a; 内核把物理页作为内存管理的基本单位。 尽管处理器的最小可寻址单位通常为字(甚至…

ZooKeeper-分布式锁实现

4.11)Zookeeper分布式锁-概念 •在我们进行单机应用开发&#xff0c;涉及并发同步的时候&#xff0c;我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题&#xff0c;这时多线程的运行都是在同一个JVM之下&#xff0c;没有任何问题。 •但当我们的应用是分…

【JavaScript】实现简易购物车

&#x1f4bb;【JavaScript】实现简易购物车 &#x1f3e0;专栏&#xff1a;有趣实用案例 &#x1f440;个人主页&#xff1a;繁星学编程&#x1f341; &#x1f9d1;个人简介&#xff1a;一个不断提高自我的平凡人&#x1f680; &#x1f50a;分享方向&#xff1a;目前主攻前端…

客快物流大数据项目(一百零四):为什么选择Elastic Search作为存储服务

文章目录 为什么选择Elastic Search作为存储服务 一、​​​​​​​​​​​​​​ElasticSearch简介

【GD32F427开发板试用】懒人新手试用

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;东东_dxGGN2 我收到的开发板是GD32F427R-START&#xff0c;MCU是GD32F427RKT6&#xff0c;如下图&#xff08;座机拍的见谅&#xff09; 测试流…

【C++】从0到1入门C++编程学习笔记 - 核心编程篇:内存分区模型

文章目录一、程序运行前二、程序运行后三、new 操作符C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释…

2022年回顾 | 被磨砺,被厚待

岁末年首&#xff0c; 最宜盘点过往的时光。 回顾2022团结一心&#xff0c;攻坚克难&#xff0c; 祝福2023大展宏图&#xff0c;鹏程万里。 2022我们遇到了"卷土重来"、 “挥之不去”&#xff0c; 也等到了"再也不见"和 “永远下线”。 2022是一个&…

HTML中的table标签与a标签

这里写自定义目录标题一、table标签1、什么是table标签2、table标签中长见到的标签3、例子代码及其结果二、a标签1、什么是a标签2、a标签中常见的属性3、例子代码及其结果一、table标签 1、什么是table标签 table标签表示整体的一个表格 2、table标签中长见到的标签 <tr…

基于Spring Boot和Spring Cloud实现微服务架构

首先&#xff0c;最想说的是&#xff0c;当你要学习一套最新的技术时&#xff0c;官网的英文文档是学习的最佳渠道。因为网上流传的多数资料是官网翻译而来&#xff0c;很多描述的重点也都偏向于作者自身碰到的问题&#xff0c;这样就很容易让你理解和操作出现偏差&#xff0c;…

采用特殊硬件指令对密码学算法加速

1. 引言 Armando Faz-Hermandez等人2018年论文《SoK: A Performance Evaluation of Cryptographic Instruction Sets on Modern Architectures》&#xff0c;开源代码见&#xff1a; https://github.com/armfazh/flo-shani-aesni&#xff08;C语言&#xff09; slide见&…

Java高手速成 | 多态性实战

多态性&#xff08;polymorphism&#xff09;是OOP最强大、最有用的特性。截至目前&#xff0c;多态性用到了所讲的所有其他OOP概念和特性。在通向精通Java语言编程的征程上&#xff0c;多态性是最高级别概念站点。 一个对象具有跟另一不同类的对象一样的行为&#xff0c;或者具…

QT5.14.2使用回顾

前面已有博客介绍了QT的安装和配置VS2019配置Qt5.14.2以及在线配置Qt5.15.2&#xff0c;这里再接着该版本说明下QT的使用&#xff0c;主要是汇总下之前博客中的内容&#xff1a;Ubuntu下的基本知识点&#xff08;二&#xff09;QT4.8.6工程到QT5.12.1的迁移注意前面安装时候&am…

小程序开发超好用的UI组件——Vant Weapp

Vant Weapp 是有赞前端团队开源的一套小程序 UI 组件库&#xff0c;助力开发者快速搭建小程序应用。它所使用的是 MIT 开源许可协议&#xff0c;对商业使用比较友好,官网地址&#xff1a;https://vant-contrib.gitee.io/vant-weapp/#/home 安装 Vant 组件库 在小程序项目中&a…

设计模式学习(十):lterator迭代器模式

一、什么是Iterator模式使用Java语言显示数组arr中的元素时&#xff0c;我们可以使用下面这样的for循环语句遍历数组。for (int i 0; i < arr.length; i){system.out.println(arr[i]); }请注意这段代码中的循环变量i。该变量的初始值是o&#xff0c;然后会递增为1,2&#x…

halo 1.4.17 使用Mysql 安装与配置

1 下载代码 https://github.com/halo-dev/halo/archive/refs/tags/v1.4.17.zip 2 查看1.4版本文档 https://docs.halo.run/1.4/ 1.3 使用idea打开并设置jdk 11 1.4 将h2配置成为mysql 修改前 修改后 1.5 打包成jar halo使用的是Gradle&#xff0c;打包时&#xff0c…

微软官宣裁员 10000 人。分享一些我的建议给大家

大家好&#xff01;我是韩老师。昨天&#xff0c;西雅图双雄经历着不眠之夜。早些时间&#xff0c;就有传言说 1 月 18 日&#xff0c;亚马逊会裁员 18000 人。微软要裁员的各种消息也是满天飞。北京时间昨天晚上&#xff0c;微软官方博客发了一篇标题为 Focusing on our short…

10. 元组tuple类型详解

python3 tuple类型的使用 1. 基本知识 a. 元组&#xff08;tuple&#xff09;与列表类似, 不同之处在于元组的元素(项)不能修改。 b. 元组写在小括号 () 里&#xff0c;元素之间用逗号隔开。 c. 元组中的元素类型也可以不相同。 d. 构造包含0个或1个元素的元组比较特殊, 所以…

自增主键为什么不是连续的?

在前面文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑。 之前我见过有的业务设计依赖于自增主键的连续性,也就是说,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不能保证连续递…

【深度学习数学基础之线性代数】研究使用链式法则进行反向传播的求导算法

链式法则 简单的说链式法则就是原本y对x求偏导&#xff0c;但是由于过程较为复杂&#xff0c;我们需要将函数进行拆分&#xff0c;通过链式进行分别求导&#xff0c;这样会使整个计算更为简单。 假设f k ( a b c ) f k(a bc)fk(abc) 通俗来说&#xff0c;链式法则表明&a…