交友项目【手机号登录注册功能】实现

目录

1:用户登录

1.1:接口文档

1.2:API接口定义

1.3:Dubbo服务提供者

配置文件

启动引导类

数据访问层

API接口实现

1.4:Dubbo服务消费者

UserController

UserService

1.5:访问测试

1.6:可能存在的问题

序列化异常

连接超时

没有服务提供者可用

2:登录涉及到JWT生成Token

2.1:简介

2.2:格式

2.3:流程

2.4:示例

2.5:JWT工具类


1:用户登录

用户接收到验证码后,进行输入验证码,点击登录,前端系统将手机号以及验证码提交到服务端进行校验。

 

1.1:接口文档

YAPI接口地址:http://192.168.136.160:3000/project/19/interface/api/97  

1.2:API接口定义

在接口模块(tanhua-dubbo-interface),将提供者模块(tanhua-dubbo-db)提供的接口抽取到一个专门的接口模块,便于统一管理,消费者模块只需要导入接口模块的依赖即可调用该接口。

 

/**
 * @Author 爱吃豆的土豆、
 * @Date 2023/3/30 11:05
 */
public interface UserApi {
    public User findByMobile(String phone);
    public Long save(User user);
}

1.3:Dubbo服务提供者

  • tanhua-dubbo-db项目中提供UserApiImpl的实现 , 如下所示

     

配置文件

server:
  port: 18081
spring:
  application:
    name: tanhua-dubbo-db
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/tanhua?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
    username: root
    password: 1234
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.136.160:8848
dubbo:
  protocol:
    name: dubbo
    port: 20881
  registry:
    address: spring-cloud://192.168.136.160:8848
  scan:
    base-packages: com.czxy.tanhua.dubbo.api  #dubbo中包扫描

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_   # 表名前缀
      id-type: auto   # id策略为自增长

启动引导类

/**
 * @Author 爱吃豆的土豆、
 * @Date 2023/3/30 14:48
 */
@SpringBootApplication
@EnableDubbo
public class DubboDBApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboDBApplication.class,args);
    }
}

数据访问层

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

API接口实现

@DubboService
public class UserApiImpl  implements UserApi {

    @Autowired
    private UserMapper userMapper;

    //根据手机号码查询用户
    public User findByMobile(String mobile) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("mobile",mobile);
        return userMapper.selectOne(qw);
    }

    @Override
    public Long save(User user) {
        userMapper.insert(user);
        return user.getId();
    }
}

1.4:Dubbo服务消费者

tanhua-app-server项目中接收APP请求, 调用Dubbo服务完成业务功能

UserController

/**
 * 校验登录
 */
@PostMapping("/loginVerification")
public ResponseEntity loginVerification(@RequestBody Map map) {
    //1 调用map集合获取请求参数
    String phone = (String) map.get("phone");
    String code = (String) map.get("verificationCode");
    //2 调用userService完成用户登录
    Map retMap = userService.loginVerification(phone, code);
    //3 构造返回
    return ResponseEntity.ok(retMap);
}

UserService

package com.czxy.tanhua.service;

import com.czxy.tanhua.autoconfig.template.SmsTemplate;
import com.czxy.tanhua.commons.utils.JwtUtils;
import com.czxy.tanhua.dubbo.api.UserApi;
import com.czxy.tanhua.entity.User;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 爱吃豆的土豆、
 * @Date 2023/3/30 9:55
 */
@Service
public class UserService {
    @Resource
    private SmsTemplate smsTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private UserApi userApi;

    /**
     * 登录用户的验证码
     * @param phone
     */
    public void loginUser(String phone) {
        //随机生成验证码
        String code = RandomStringUtils.randomNumeric(6);
        //调用短信工具类
        smsTemplate.sendSms(phone,"",code);
        String key = "CHECK_CODE"+phone;
        //存放到redis中
        stringRedisTemplate.opsForValue().set(key,code,Duration.ofMinutes(5));

    }

    /**
     * 登录验证码的校验&用户注册
     * @param map
     * @return
     */
    public Map loginVerification(Map map) {
        String phone = (String) map.get("phone");
        String verificationCode = (String) map.get("verificationCode");

        //将验证码进行校验
        String s = stringRedisTemplate.opsForValue().get("CHECK_CODE" + phone);
        //取出之后删除验证码
        stringRedisTemplate.delete("CHECK_CODE"+phone);

        if (StringUtils.isEmpty(s) || !s.equals(verificationCode)){
            throw new RuntimeException("验证码校验失败!");
        }
        //判断用户是否已经注册
        Boolean isNew = false;
        //验证码校验成功,查询数据库是否存在该用户
        User user = userApi.findByMobile(phone);
        if (user == null){
            //新注册用户
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            //进行添加到数据库中
            Long id = userApi.save(user);
            user.setId(id);
            isNew = true;
        }
        //号码已经再数据库中存在生成token进行返回
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id",user.getId());
        tokenMap.put("mobile", user.getMobile());
        String token = JwtUtils.getToken(tokenMap);
        Map<String, Object> result = new HashMap<>();
        result.put("token",token);
        result.put("isNew",isNew);
        return result;
    }
}

1.5:访问测试

【第一步】查看ip地址黑窗口ipconfig

【第二步】修改服务配置:【自己电脑的IP地址】  

 【第三步】测试

 

1.6:可能存在的问题

序列化异常

 

连接超时

Nacos连接超时 ,Redis连接超时等

等待很长时间, 报如下类似的错误

 

找到连接超时的服务 :

  1. 查看服务是否启动

  2. 查看服务连接配置IP端口是否正确

  3. 查看开发机器和服务所在机器网络是否通畅(ping指令)

没有服务提供者可用

没有服务提供者可用

  1. 检查服务提供者工程是否开启成功

  2. 检查注册中心是否存在该服务

  3. 注册中心不存在 服务

    1. 检查dubbo扫描的包是否正确

    2. 检查@DubboService注解是否添加

  4. 注册中心存在服务

    1. 检查服务消费方的注册中心地址是否正确

    2. 检查提供方和消费方的接口定义是否相同

 

2:登录涉及到JWT生成Token

2.1:简介

  • JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记。也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据。此特性便于可伸缩性, 同时保证应用程序的安全

2.2:格式

  • JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为:A.B.C

  • A由JWT头部信息header加密得到

  • B由JWT用到的身份验证信息json数据加密得到

  • C由A和B加密得到,是校验部分

 

2.3:流程

 

2.4:示例

导入依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency

编写测试用例:  

@Test
public void testCreateToken() {
    //生成token
    //1 准备数据
    Map map = new HashMap();
    map.put("id",1);
    map.put("mobile","13612345678");
    //2 使用JWT的工具类生成token
    long now = System.currentTimeMillis();
    String token = Jwts.builder()
            .signWith(SignatureAlgorithm.HS512, "czxy") //指定加密算法
            .setClaims(map) //写入数据
            .setExpiration(new Date(now + 30000)) //失效时间
            .compact();
    System.out.println(token);
}

//解析token

/**
 * SignatureException : token不合法
 * ExpiredJwtException:token已过期
 */
@Test
public void testParseToken() {
    String token = "eyJhbGciOiJIUzUxMiJ9.eyJtb2JpbGUiOiIxMzgwMDEzODAwMCIsImlkIjoxLCJleHAiOjE2MTgzOTcxOTV9.2lQiovogL5tJa0px4NC-DW7zwHFqZuwhnL0HPAZunieGphqnMPduMZ5TtH_mxDrgfiskyAP63d8wzfwAj-MIVw";
    try {
        Claims claims = Jwts.parser()
                .setSigningKey("czxy")
                .parseClaimsJws(token)
                .getBody();
        Object id = claims.get("id");
        Object mobile = claims.get("mobile");
        System.out.println(id + "--" + mobile);
    }catch (ExpiredJwtException e) {
        System.out.println("token已过期");
    }catch (SignatureException e) {
        System.out.println("token不合法");
    }

}

通过解析Token得知,如果抛出SignatureException异常表示token不合法,如果抛出ExpiredJwtException异常表示token已过期  

2.5:JWT工具类

tanhua-commons 模块创建JWT工具类

public class JwtUtils {

    // TOKEN的有效期1小时(S)
    private static final int TOKEN_TIME_OUT = 3_600;

    // 加密KEY
    private static final String TOKEN_SECRET = "czxy";


    // 生成Token
    public static String getToken(Map params){
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, TOKEN_SECRET) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳
                .addClaims(params)
                .compact();
    }


    /**
     * 获取Token中的claims信息
     */
    private static Claims getClaims(String token) {
        return Jwts.parser()
                .setSigningKey(TOKEN_SECRET)
                .parseClaimsJws(token).getBody();
    }


    /**
     * 是否有效 true-有效,false-失效
     */
    public static boolean verifyToken(String token) {
      
        if(StringUtils.isEmpty(token)) {
            return false;
        }
        
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(TOKEN_SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e) {
            return false;
        }

		return true;
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Django 网页Web开发】23. 实战项目:Excel和form和moudleForm的文件上传(16)(保姆级图文)

目录excel文件批量上传数据1. depart_list.html2. url.py3. moudle.py4. depart.py5. upload.pyform文件上传1. upload_form.html2. url.py3. moudle.py4. upload.py5. 目录media存放用户上传的文件总结欢迎关注 『Django 网页Web开发』 系列&#xff0c;持续更新中 欢迎关注 『…

PHY- PHY芯片概述

1 PHY概述 关于Internet Protocal的分层模型可以参考文章 :【Internet Protocal-OSI模型中的网络分层模型】,下面我们讲讲底层以太网控制器和收发器的知识。其主要是处理OSI模型中的物理层和链路层的事情。 在CAN/CANFD、FlexRay等总线中,有控制器Controller和收发器Transc…

【华为OD机试】1024 - 素数伴侣

文章目录一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1&#x1f538;样例2二、思路解析三、代码参考作者&#xff1a;KJ.JK&#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &…

Ae:灯光选项

灯光选项 Light Options&#xff0c;用于调整光源的特性以及所产生的投影的相关设置。下面以属性最多的聚光灯的灯光选项为例进行说明。强度 Intensity光源的亮度。数值越大&#xff0c;光照越大。负值可产生吸光效果&#xff0c;即降低场景中其它光源的光照强度。颜色 Color默…

Java客户端操作索引库

ElasticSearch第二天 学习目标&#xff1a; 能够使用java客户端完成创建、删除索引的操作能够使用java客户端完成文档的增删改的操作能够使用java客户端完成文档的查询操作能够完成文档的分页操作能够完成文档的高亮查询操作能够搭建Spring Data ElasticSearch的环境能够完成…

C++中的类模版

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…

银行数字化转型导师坚鹏:金融科技与银行转型

金融科技与银行转型课程背景&#xff1a; 数字化背景下&#xff0c;很多银行存在以下问题&#xff1a; 不清楚5G如何赋能银行数字化转型&#xff1f; 不清楚金融科技如何赋能银行数字化转型&#xff1f; 不了解银行数字化转型标杆成功案例&#xff1f; 课程特色&#xff1a;…

Python 进阶指南(编程轻松进阶):十七、Python 风格 OOP:属性和魔术方法

原文&#xff1a;http://inventwithpython.com/beyond/chapter17.html 很多语言都有 OOP 特性&#xff0c;但是 Python 有一些独特的 OOP 特性&#xff0c;包括属性和魔术方法。学习如何使用这些 Python 风格技巧可以帮助您编写简洁易读的代码。 属性允许您在每次读取、修改或…

Leetcode.993 二叉树的堂兄弟节点

题目链接 Leetcode.993 二叉树的堂兄弟节点 Rating &#xff1a; 1288 题目描述 在二叉树中&#xff0c;根节点位于深度 0 处&#xff0c;每个深度为 k 的节点的子节点位于深度 k1 处。 如果二叉树的两个节点深度相同&#xff0c;但 父节点不同 &#xff0c;则它们是一对堂兄…

Java IO相关

1、深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象 深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其…

生成式AI已形成全球性“AI再造业务”趋势

3月28日至31日&#xff0c;博鳌亚洲论坛2023年年会在海南举行。实体经济与数字经济如何融合发展&#xff0c;产业数字化如何加速向深层次拓展&#xff0c;生成式AI会给产业经济带来哪些变革&#xff1f;这些话题成为今年论坛热点。 百度集团执行副总裁、百度智能云事业群总裁沈…

鸟哥的Linux私房菜 学习 Shell Scripts

第十三章、学习 Shell Scripts 重点回顾 shell script 是利用 shell 的功能所写的一个『程序 (program)』&#xff0c;这个程序是使用纯文字档&#xff0c;将一些 shell 的语法与命令(含外部命令)写在里面&#xff0c; 搭配正规表示法、管线命令与数据流重导向等功能&#xf…

MacBookPro 安装Python

Homebrew 假设你没有安装Homebrew&#xff0c;那么就执行&#xff1a; /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)”安装Python 执行命令&#xff1a; yutaoMacBook-Pro Homebrew % brew install Python可以看到…

第一个禁止ChatGPT的西方国家

意大利成为第一个有效禁止 ChatGPT 的西方国家。 由于可能违反隐私和数据法&#xff0c;该国的数据监管机构已下令开发聊天机器人的 OpenAI 停止运营。 意大利数据保护局 (GPDP) 提到了一些担忧&#xff0c;包括大量收集用户数据和存储以训练 AI 算法。 ChatGPT 是一种大型语…

产品经理必读|用户研究方法总结①

众所周知&#xff0c;理解用户需求&#xff0c;识别用户痛点&#xff0c;是产品或功能成型之前绕不开的过程。而要获取到用户真实的需求和痛点&#xff0c;唯一的方法就是做用户调研。而用研的方法都有哪些呢&#xff1f;今天我就来给大家分享一下行业中常见的用研方法。 用研的…

C. Triangles(枚举)

Problem - C - Codeforces Gildong有一个方形板&#xff0c;由n行n列的方形单元格组成&#xff0c;每个单元格由一个数字(从0到9)组成&#xff0c;第i行第j列的单元格可用(&#xff0c;)表示&#xff0c;每个单元格的边长为1。Gildong喜欢大的东西&#xff0c;所以对于每一个数…

个人-计算机操作系统第六章

第六章 输入输出系统 一、章节习题 1、引入缓冲的主要目的______ A 改善CPU和I/O设备之间速度不匹配的情况 B 节省内存 C 提高CPU的利用率 D 提高I/O设备的效率 2、CPU输出数据的速度远远高于打印机的打印速度&#xff0c;为了解决这一矛盾&#xff0c;可采用_____。 A …

geth指定版本安装

下载源码 cd /usr/local git clone https://github.com/ethereum/go-ethereum.git 或者(mirror) git clone https://ghproxy.com/https://github.com/ethereum/go-ethereum.git拓展&#xff1a;如何git clone指定tag版本 git clone -b v1.10.5 https://github.com/ethereum/…

不要告诉同事你要离职!打算跳槽,新公司开出两倍薪资,私下告诉要好的同事,却被同事出卖给领导!...

职场上有真正的朋友吗&#xff1f;来看看这位网友的讲述&#xff1a;一位前同事本来打算跳槽&#xff0c;新公司开出的薪资是原来的两倍。她私下告诉了几位同事自己打算离职的消息&#xff0c;并跟同事们分享了工资翻倍的喜悦。可她万万没想到&#xff0c;两天之后的公司会议上…

Python 进阶指南(编程轻松进阶):十六、面向对象编程和继承

原文&#xff1a;http://inventwithpython.com/beyond/chapter16.html 定义一个函数&#xff0c;并从几个地方调用它&#xff0c;可以省去复制和粘贴源代码的麻烦。不复制代码是一个很好的实践&#xff0c;因为如果你需要修改它&#xff08;无论是为了修复一个错误还是添加新特…
最新文章