目录

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-dbdatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/tanhua?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=falseusername: rootpassword: 1234cloud:nacos:discovery:server-addr: 192.168.136.160:8848
dubbo:protocol:name: dubboport: 20881registry:address: spring-cloud://192.168.136.160:8848scan: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 {@Autowiredprivate UserMapper userMapper;//根据手机号码查询用户public User findByMobile(String mobile) {QueryWrapper<User> qw = new QueryWrapper<>();qw.eq("mobile",mobile);return userMapper.selectOne(qw);}@Overridepublic 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 {@Resourceprivate SmsTemplate smsTemplate;@Resourceprivate StringRedisTemplate stringRedisTemplate;@DubboReferenceprivate 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的工具类生成tokenlong 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;// 加密KEYprivate static final String TOKEN_SECRET = "czxy";// 生成Tokenpublic 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;}
}

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

  1. Vue项目二 登录注册功能的实现

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.系统注册功能的实现 1.配置注册页面路由 2.注册页面的搭建 3.api下发送ajax请求的文件创建 二.后台数据 ...

  2. javaweb开发的仿推特项目之登录注册功能

    博主最近学习一个仿推特javaweb项目,其采用Jsp+Servlet的方式进行设计,MySQL数据库,Tomcat8服务,界面上十分美观,功能也较为健全,给大家分享一下: 项目地址 登录界面: 核心 ...

  3. 使用JSP实现简单的登录注册功能,并且使用Session跟踪用户登录信息

    使用JSP实现简单的登录注册功能,并且使用了Session来跟踪用户的登录信息,这个是用纯JSP来实现此功能的,由于没有连接数据库,所以使用List来模拟数据库. 第一步:创建web项目 如果有不会创 ...

  4. MVC框架实现用户的登录注册功能

    MVC是什么? MVC,全称model view controller-模型,视图,控制器 model是将数据库中的表到Java中变成实体类 view是编写JSP页面 controller是用来业务逻 ...

  5. 在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)

    在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库) 完整的项目已上传github仓库,链接在文章最下面 注:笔者在安卓客户端部分写了kotlin语言和java语 ...

  6. Android登录注册功能封装

    我们都知道Android应用软件基本上都会用到登录注册功能,那么对一个一个好的登录注册模块进行封装就势在必行了.这里给大家介绍一下我的第一个项目中所用到的登录注册功能的,已经对其进行封装,希望能对大家 ...

  7. Django(二)精美博客搭建(1)实现登录/注册功能

    前言 之前我们用Django框架做了一个很简单的个人博客搭建,不论是页面还是功能都很粗糙 所以从这篇开始我打算做一个比较完整的[个人博客网站],可能会分好几篇博客来讲述 等所有功能完善的差不多后,再考 ...

  8. node mysql登录注册_图解NodeJS实现登录注册功能

    该Demo根据菜鸟教程的练手项目,请提前到菜鸟教程的官网查看nodejs的相关教程,根据教程实际操作一遍,然后自己动手去实现登录.注册功能,此Demo只作参考,不符合前端相关规范. 使用的技术栈 no ...

  9. java wed登录面 代码_JavaWeb实现用户登录注册功能实例代码(基于Servlet+JSP+JavaBean模式)...

    下面通过通过图文并茂的方式给大家介绍JavaWeb实现用户登录注册功能实例代码,一起看看吧. 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+JavaBea ...

最新文章

  1. ionic 项目中添加modal的步骤流程
  2. 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )
  3. 【笔记】HMM在股票指数中的简单应用
  4. 做俯卧撑的10个技巧
  5. JAVA元注解@interface详解(@Target,@Documented,@Retention,@Inherited)。
  6. C#将照片或图片转化为byte[]存入数据库,从数据库中读照片
  7. python链接mysql系统结构设计_MySQLpython交互
  8. [转载] mac开发者,你不得不知道的环境变更设置方法(如Java的环境变更 source命令 )
  9. 工行高级经理林承军:工行基于 MySQL 构建分布式架构的转型之路
  10. 东风畅行java_东风畅行载货车为何可以口碑很好吗?是配置高?或者另有原因?...
  11. java.sql.SQLException: ORA01555: 快照过旧: 回退段号 4 过小
  12. recvfrom函数 非阻塞_那些年让你迷惑的阻塞、非阻塞、异步、同步
  13. consul服务发现与注册于配置 (mac版为例)
  14. JAVA 实现《2048游戏》游戏
  15. oracle 保留池,oracle的内存结构之--查看内存信息+保留池和循环池(摘自文平书)...
  16. 数据结构教程(第5版)李春葆 课后习题及答案(PDF版)
  17. 计算器软件设计和计算机软件设计区别,基于LabVIEW的计算器程序设计
  18. 使用大白菜装win10系统的常见问题解决方案
  19. 为什么单线程的Redis如此的快(Why is single-threaded Redis so fast)
  20. PHP实现小型问卷星,JS实现问卷星自动填问卷脚本并在两秒自动提交功能

热门文章

  1. 百度地图API Android SDK 常见问题
  2. Python PTA实验课 求小于某一大于2的自然数的所有素数
  3. nn.CrossEntropyLoss的ignore_index标签(CE loss)
  4. Vivado综合设置之-gated_clock_conversion
  5. 目标Zookeeper未授权访问(漏洞验证)
  6. 卷积神经网络的形象理解
  7. 锁相环(PLL)基本原理与频率合成器
  8. C++11条件变量:notify_one()与notify_all()的区别
  9. 各种JSON技术对比(Json-lib,Jackson,Gson,Fastjson)
  10. LeetCode 1278. 分割回文串 III