springboot + vue + sso单点登录 + 短信验证码 + JWT 实现登录注册功能

ゝ一纸荒年。 2024-04-06 10:14 162阅读 0赞

用户登录业务介绍

1.1、单一服务器模式

早期单一服务器,用户认证。
在这里插入图片描述

缺点:单点性能压力,无法扩展。

1.2、SSO(single sign on)模式

分布式,SSO(single sign on)模式
在这里插入图片描述

单点登录常见的方式
在这里插入图片描述

优点 :

  • 用户身份信息独立管理,更好的分布式管理。
  • 可以自己扩展安全策略

缺点:

  • 认证服务器访问压力较大。
1.3、Token模式

业务流程图{用户访问业务时,必须登录的流程}
在这里插入图片描述

优点:

  • 无状态: token无状态,session有状态的
  • 基于标准化: 你的API可以采用标准化的 JSON Web Token (JWT)

缺点:

  • 占用带宽
  • 无法在服务器端销毁

注:基于微服务开发,选择token的形式相对较多。

JWT介绍

2.1、使用JWT进行跨域身份验证
2.1.1、传统用户身份验证

在这里插入图片描述

Internet服务无法与用户身份验证分开。一般过程如下:

  1. 用户向服务器发送用户名和密码。
  2. 验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中。
  3. 服务器向用户返回session_id,session信息都会写入到用户的Cookie。
  4. 用户的每个后续请求都将通过在Cookie中取出session_id传给服务器。
  5. 服务器收到session_id并对比之前保存的数据,确认用户的身份。

这种模式最大的问题是,没有分布式架构,无法支持横向扩展。

2.1.2、解决方案
  1. session广播
  2. 将透明令牌存入cookie,将用户身份信息存入redis

另外一种灵活的解决方案:使用自包含令牌,通过客户端保存数据,而服务器不保存会话数据。 JWT是这种解决方案的代表。

2.2、JWT令牌
2.2.1、访问令牌的类型

在这里插入图片描述

2.2.2、JWT的组成

典型的,一个JWT看起来如下图:
在这里插入图片描述

该对象为一个很长的字符串,字符之间通过”.”分隔符分为三个子串。
每一个子串表示了一个功能块,总共有以下三个部分:JWT头、有效载荷和签名。

  • JWT头

    JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

    {
    “alg”: “HS256”,
    “typ”: “JWT”
    }

在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

  • 有效载荷

    有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。

    iss:发行人
    exp:到期时间
    sub:主题
    aud:用户
    nbf:在此之前不可用
    iat:发布时间
    jti:JWT ID用于标识该JWT

除以上默认字段外,我们还可以自定义私有字段,如下例:

  1. {
  2. "sub": "1234567890",
  3. "name": "Helen",
  4. "admin": true
  5. }

请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

JSON对象也使用Base64 URL算法转换为字符串保存。

  • 签名哈希

    签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。

    首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。

    HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(claims), secret)

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用”.”分隔,就构成整个JWT对象。

Base64URL算法

如前所述,JWT头和有效载荷序列化的算法都用到了Base64URL。该算法和常见Base64算法类似,稍有差别。

作为令牌的JWT可以放在URL中(例如api.example/?token=xxx)。 Base64中用的三个字符是”+“,”/“和”=“,由于在URL中有特殊含义,因此Base64URL中对他们做了替换:”=“去掉,”+“用”-“替换,”/“用”_“替换,这就是Base64URL算法。

2.2.3、JWT的原则

JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,如下所示。

  1. {
  2. "sub": "1234567890",
  3. "name": "Helen",
  4. "admin": true
  5. }

之后,当用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名。

服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展。

2.2.4、JWT的用法

客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。

此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。当跨域时,也可以将JWT被放置于POST请求的数据主体中。

2.2.5、JWT问题和趋势
  1. JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
  2. 生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库。
  3. 存储在客户端,不占用服务端的内存资源。
  4. JWT默认不加密,但可以加密。生成原始令牌后,可以再次对其进行加密。
  5. 当JWT未加密时,一些私密数据无法通过JWT传输。
  6. JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
  7. JWT本身包含认证信息,token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
  8. 为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。
2.3、springboot整合JWT
2.3.1、引入依赖
  1. <!-- JWT-->
  2. <dependency>
  3. <groupId>io.jsonwebtoken</groupId>
  4. <artifactId>jjwt</artifactId>
  5. </dependency>
2.3.2、创建JWT工具类
  1. package com.atguigu.commonutils;
  2. import io.jsonwebtoken.Claims;
  3. import io.jsonwebtoken.Jws;
  4. import io.jsonwebtoken.Jwts;
  5. import io.jsonwebtoken.SignatureAlgorithm;
  6. import org.springframework.http.server.reactive.ServerHttpRequest;
  7. import org.springframework.util.StringUtils;
  8. import javax.servlet.http.HttpServletRequest;
  9. import java.util.Date;
  10. /**
  11. * JWT工具类
  12. */
  13. public class JwtUtils {
  14. //常量
  15. public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间
  16. public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //秘钥
  17. //生成token字符串的方法
  18. public static String getJwtToken(String id, String nickname){
  19. String JwtToken = Jwts.builder()
  20. .setHeaderParam("typ", "JWT")
  21. .setHeaderParam("alg", "HS256")
  22. .setSubject("guli-user")
  23. .setIssuedAt(new Date())
  24. .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
  25. .claim("id", id) //设置token主体部分 ,存储用户信息
  26. .claim("nickname", nickname)
  27. .signWith(SignatureAlgorithm.HS256, APP_SECRET)
  28. .compact();
  29. return JwtToken;
  30. }
  31. /**
  32. * 判断token是否存在与有效
  33. * @param jwtToken
  34. * @return
  35. */
  36. public static boolean checkToken(String jwtToken) {
  37. if(StringUtils.isEmpty(jwtToken)) return false;
  38. try {
  39. Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  40. } catch (Exception e) {
  41. e.printStackTrace();
  42. return false;
  43. }
  44. return true;
  45. }
  46. /**
  47. * 判断token是否存在与有效
  48. * @param request
  49. * @return
  50. */
  51. public static boolean checkToken(HttpServletRequest request) {
  52. try {
  53. String jwtToken = request.getHeader("token");
  54. if(StringUtils.isEmpty(jwtToken)) return false;
  55. Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. return false;
  59. }
  60. return true;
  61. }
  62. /**
  63. * 根据token字符串获取会员id
  64. * @param request
  65. * @return
  66. */
  67. public static String getMemberIdByJwtToken(HttpServletRequest request) {
  68. String jwtToken = request.getHeader("token");
  69. if(StringUtils.isEmpty(jwtToken)) return "";
  70. Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  71. Claims claims = claimsJws.getBody();
  72. return (String)claims.get("id");
  73. }
  74. }

阿里云 短信服务

3.1、开通阿里云短信服务
3.1.1、进入短信服务

在这里插入图片描述

3.1.2、快速学习,创建自己的模板和签名

在这里插入图片描述

3.1.3、审核通过

在这里插入图片描述在这里插入图片描述

3.2、springboot整合短信服务
3.2.1、创建短信服务模块

在这里插入图片描述

3.2.2、配置application.properties
  1. # 服务端口
  2. server.port=8005
  3. # 服务名
  4. spring.application.name=service-msm
  5. # mysql数据库连接
  6. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  7. spring.datasource.url=jdbc:mysql://localhost:3306/guli_education?serverTimezone=GMT%2B8
  8. spring.datasource.username=root
  9. spring.datasource.password=zzybzb
  10. spring.redis.host=127.0.0.1
  11. spring.redis.port=6379
  12. spring.redis.database= 0
  13. spring.redis.timeout=1800000
  14. spring.redis.lettuce.pool.max-active=20
  15. spring.redis.lettuce.pool.max-wait=-1
  16. #最大阻塞等待时间(负数表示没限制)
  17. spring.redis.lettuce.pool.max-idle=5
  18. spring.redis.lettuce.pool.min-idle=0
  19. #最小空闲
  20. #返回json的全局时间格式
  21. spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
  22. spring.jackson.time-zone=GMT+8
  23. #mybatis日志
  24. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  25. # nacos服务地址
  26. spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3.2.3、创建启动类
  1. @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源自动配置
  2. @ComponentScan("com.atguigu")
  3. public class MsmApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(MsmApplication.class,args);
  6. }
  7. }
3.2.4、引入依赖
  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>com.aliyun</groupId>
  7. <artifactId>aliyun-java-sdk-core</artifactId>
  8. </dependency>
3.2.5、生成随机验证码的工具类
  1. package com.atguigu.msmservice.utils;
  2. import java.text.DecimalFormat;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Random;
  7. /**
  8. * 获取随机数
  9. *
  10. * @author qianyi
  11. *
  12. */
  13. public class RandomUtil {
  14. private static final Random random = new Random();
  15. private static final DecimalFormat fourdf = new DecimalFormat("0000");
  16. private static final DecimalFormat sixdf = new DecimalFormat("000000");
  17. public static String getFourBitRandom() {
  18. return fourdf.format(random.nextInt(10000));
  19. }
  20. public static String getSixBitRandom() {
  21. return sixdf.format(random.nextInt(1000000));
  22. }
  23. /**
  24. * 给定数组,抽取n个数据
  25. * @param list
  26. * @param n
  27. * @return
  28. */
  29. public static ArrayList getRandom(List list, int n) {
  30. Random random = new Random();
  31. HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
  32. // 生成随机数字并存入HashMap
  33. for (int i = 0; i < list.size(); i++) {
  34. int number = random.nextInt(100) + 1;
  35. hashMap.put(number, i);
  36. }
  37. // 从HashMap导入数组
  38. Object[] robjs = hashMap.values().toArray();
  39. ArrayList r = new ArrayList();
  40. // 遍历数组并打印数据
  41. for (int i = 0; i < n; i++) {
  42. r.add(list.get((int) robjs[i]));
  43. System.out.print(list.get((int) robjs[i]) + "\t");
  44. }
  45. System.out.print("\n");
  46. return r;
  47. }
  48. }
3.2.6、编写controller,根据手机号发送短信
  1. package com.atguigu.msmservice.controller;
  2. import com.atguigu.commonutils.R;
  3. import com.atguigu.msmservice.service.MsmService;
  4. import com.atguigu.msmservice.utils.RandomUtil;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.data.redis.core.RedisTemplate;
  7. import org.springframework.util.StringUtils;
  8. import org.springframework.web.bind.annotation.*;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. import java.util.concurrent.TimeUnit;
  12. @RestController
  13. @RequestMapping("/edumsm/msm")
  14. @CrossOrigin
  15. public class MsmController {
  16. @Autowired
  17. private MsmService msmService;
  18. @Autowired
  19. private RedisTemplate<String,String> redisTemplate;
  20. //发送短信的方法
  21. @GetMapping("send/{phone}")
  22. public R sendMsm(@PathVariable String phone) {
  23. //1 从redis获取验证码,如果获取到直接返回
  24. String code = redisTemplate.opsForValue().get(phone);
  25. if(!StringUtils.isEmpty(code)) {
  26. return R.ok();
  27. }
  28. //2 如果redis获取 不到,进行阿里云发送
  29. //生成随机值,传递阿里云进行发送
  30. code = RandomUtil.getFourBitRandom();
  31. Map<String,Object> param = new HashMap<>();
  32. param.put("code",code);
  33. //调用service发送短信的方法
  34. boolean isSend = msmService.send(param,phone);
  35. if(isSend) {
  36. //发送成功,把发送成功验证码放到redis里面
  37. //设置有效时间
  38. redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
  39. return R.ok();
  40. } else {
  41. return R.error().message("短信发送失败");
  42. }
  43. }
  44. }
3.2.7、编写service
  1. package com.atguigu.msmservice.service.impl;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.aliyuncs.CommonRequest;
  4. import com.aliyuncs.CommonResponse;
  5. import com.aliyuncs.DefaultAcsClient;
  6. import com.aliyuncs.IAcsClient;
  7. import com.aliyuncs.http.MethodType;
  8. import com.aliyuncs.profile.DefaultProfile;
  9. import com.atguigu.msmservice.service.MsmService;
  10. import org.springframework.stereotype.Service;
  11. import org.springframework.util.StringUtils;
  12. import java.util.Map;
  13. @Service
  14. public class MsmServiceImpl implements MsmService {
  15. //发送短信的方法
  16. @Override
  17. public boolean send(Map<String, Object> param, String phone) {
  18. if(StringUtils.isEmpty(phone)) return false;
  19. DefaultProfile profile =
  20. DefaultProfile.getProfile("default", "自己的阿里云oss的keyid", "自己阿里云oss的keysecret");
  21. IAcsClient client = new DefaultAcsClient(profile);
  22. //设置相关固定的参数
  23. CommonRequest request = new CommonRequest();
  24. //request.setProtocol(ProtocolType.HTTPS);
  25. request.setMethod(MethodType.POST);
  26. request.setDomain("dysmsapi.aliyuncs.com");
  27. request.setVersion("2017-05-25");
  28. request.setAction("SendSms");
  29. //设置发送相关的参数
  30. request.putQueryParameter("PhoneNumbers",phone); //手机号
  31. request.putQueryParameter("SignName","短信签名名称"); //申请阿里云 签名名称
  32. request.putQueryParameter("TemplateCode","短信模板code"); //申请阿里云 模板code
  33. request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param)); //验证码数据,转换json数据传递
  34. try {
  35. //最终发送
  36. CommonResponse response = client.getCommonResponse(request);
  37. boolean success = response.getHttpResponse().isSuccess();
  38. return success;
  39. }catch(Exception e) {
  40. e.printStackTrace();
  41. return false;
  42. }
  43. }
  44. }

登录注册后端

4.1、创建用户模块

在这里插入图片描述

4.2、配置文件application
  1. # 服务端口
  2. server.port=8006
  3. # 服务名
  4. spring.application.name=service-ucenter
  5. # mysql数据库连接
  6. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  7. spring.datasource.url=jdbc:mysql://localhost:3306/guli_education?serverTimezone=GMT%2B8
  8. spring.datasource.username=root
  9. spring.datasource.password=zzybzb
  10. spring.redis.host=127.0.0.1
  11. spring.redis.port=6379
  12. spring.redis.database= 0
  13. spring.redis.timeout=1800000
  14. spring.redis.lettuce.pool.max-active=20
  15. spring.redis.lettuce.pool.max-wait=-1
  16. #最大阻塞等待时间(负数表示没限制)
  17. spring.redis.lettuce.pool.max-idle=5
  18. spring.redis.lettuce.pool.min-idle=0
  19. #最小空闲
  20. #返回json的全局时间格式
  21. spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
  22. spring.jackson.time-zone=GMT+8
  23. #配置mapper xml文件的路径
  24. mybatis-plus.mapper-locations=classpath:com/atguigu/educenter/mapper/xml/*.xml
  25. #mybatis日志
  26. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  27. # nacos服务地址
  28. spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
4.3、创建RegisterVo用于接收注册数据封装
  1. @Data
  2. public class RegisterVo {
  3. @ApiModelProperty(value = "昵称")
  4. private String nickname;
  5. @ApiModelProperty(value = "手机号")
  6. private String mobile;
  7. @ApiModelProperty(value = "密码")
  8. private String password;
  9. @ApiModelProperty(value = "验证码")
  10. private String code;
  11. }
4.4、MD5加密工具类
  1. package com.atguigu.commonutils;
  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;
  4. public final class MD5 {
  5. public static String encrypt(String strSrc) {
  6. try {
  7. char hexChars[] = {
  8. '0', '1', '2', '3', '4', '5', '6', '7', '8',
  9. '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  10. byte[] bytes = strSrc.getBytes();
  11. MessageDigest md = MessageDigest.getInstance("MD5");
  12. md.update(bytes);
  13. bytes = md.digest();
  14. int j = bytes.length;
  15. char[] chars = new char[j * 2];
  16. int k = 0;
  17. for (int i = 0; i < bytes.length; i++) {
  18. byte b = bytes[i];
  19. chars[k++] = hexChars[b >>> 4 & 0xf];
  20. chars[k++] = hexChars[b & 0xf];
  21. }
  22. return new String(chars);
  23. } catch (NoSuchAlgorithmException e) {
  24. e.printStackTrace();
  25. throw new RuntimeException("MD5加密出错!!+" + e);
  26. }
  27. }
  28. public static void main(String[] args) {
  29. System.out.println(MD5.encrypt("111111"));
  30. }
  31. }
4.5、controller
  1. package com.atguigu.educenter.controller;
  2. import com.atguigu.commonutils.JwtUtils;
  3. import com.atguigu.commonutils.R;
  4. import com.atguigu.educenter.entity.UcenterMember;
  5. import com.atguigu.educenter.entity.vo.RegisterVo;
  6. import com.atguigu.educenter.service.UcenterMemberService;
  7. import com.atguigu.servicebase.exceptionhandler.GuliException;
  8. import io.swagger.annotations.Api;
  9. import io.swagger.annotations.ApiOperation;
  10. import org.apache.commons.lang.StringUtils;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.web.bind.annotation.*;
  13. import javax.servlet.http.HttpServletRequest;
  14. /**
  15. * <p>
  16. * 会员表 前端控制器
  17. * </p>
  18. *
  19. * @author pzz
  20. * @since 2022-09-17
  21. */
  22. @Api("用户登录注册")
  23. @RestController
  24. @RequestMapping("/educenter/member")
  25. @CrossOrigin
  26. public class UcenterMemberController {
  27. @Autowired
  28. private UcenterMemberService memberService;
  29. @ApiOperation("登录")
  30. @PostMapping("/login")
  31. public R login(@RequestBody UcenterMember ucenterMember){
  32. //member对象封装手机号和密码
  33. //调用service方法实现登录
  34. //返回token值,使用jwt生成
  35. String token = memberService.login(ucenterMember);
  36. return R.ok().data("token",token);
  37. }
  38. @ApiOperation("注册")
  39. @PostMapping("/register")
  40. public R register(@RequestBody RegisterVo registerVo){
  41. memberService.register(registerVo);
  42. return R.ok();
  43. }
  44. //根据token获取用户信息
  45. @GetMapping("getMemberInfo")
  46. public R getMemberInfo(HttpServletRequest request){
  47. //调用jwt工具类的方法。根据request对象获取头信息,返回用户id
  48. String memberId = JwtUtils.getMemberIdByJwtToken(request);
  49. UcenterMember member = memberService.getById(memberId);
  50. return R.ok().data("userInfo",member);
  51. }
  52. }
4.6、service
  1. package com.atguigu.educenter.service.impl;
  2. import com.atguigu.commonutils.JwtUtils;
  3. import com.atguigu.commonutils.MD5;
  4. import com.atguigu.commonutils.R;
  5. import com.atguigu.educenter.entity.UcenterMember;
  6. import com.atguigu.educenter.entity.vo.RegisterVo;
  7. import com.atguigu.educenter.mapper.UcenterMemberMapper;
  8. import com.atguigu.educenter.service.UcenterMemberService;
  9. import com.atguigu.servicebase.exceptionhandler.GuliException;
  10. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  11. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  12. import org.apache.commons.lang.StringUtils;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.stereotype.Service;
  16. /**
  17. * <p>
  18. * 会员表 服务实现类
  19. * </p>
  20. *
  21. * @author pzz
  22. * @since 2022-09-17
  23. */
  24. @Service
  25. public class UcenterMemberServiceImpl extends ServiceImpl<UcenterMemberMapper, UcenterMember> implements UcenterMemberService {
  26. @Autowired
  27. private RedisTemplate<String,String> redisTemplate;
  28. /**
  29. * 登录
  30. * @param ucenterMember
  31. * @return
  32. */
  33. @Override
  34. public String login(UcenterMember ucenterMember) {
  35. //获取登录的手机和密码
  36. String mobile = ucenterMember.getMobile();
  37. String password = ucenterMember.getPassword();
  38. //判断输入的手机号和密码是否为空
  39. if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)){
  40. throw new GuliException(20001,"登录失败:手机和密码不能为空");
  41. }
  42. //判断手机号是否正确
  43. QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
  44. wrapper.eq("mobile",mobile);
  45. UcenterMember ucenterMemberDB = baseMapper.selectOne(wrapper);
  46. //判断查询的对象是否为空
  47. if(ucenterMemberDB == null){
  48. throw new GuliException(20001,"登录失败:手机号不存在");
  49. }
  50. //判断密码
  51. //因为存储到数据库密码肯定加密的
  52. //把输入的密码进行加密,再和数据库密码进行比较
  53. //加密方式 MD5
  54. if(!MD5.encrypt(password).equals(ucenterMemberDB.getPassword())){
  55. throw new GuliException(20001,"登录失败:密码错误");
  56. }
  57. //判断用户是否禁用
  58. if (ucenterMemberDB.getIsDisabled()){
  59. throw new GuliException(20001,"登录失败:该用户已被禁用");
  60. }
  61. //登录成功
  62. //生成token字符串,使用jwt工具类
  63. String token = JwtUtils.getJwtToken(ucenterMemberDB.getId(), ucenterMemberDB.getNickname());
  64. return token;
  65. }
  66. /**
  67. * 注册
  68. * @param registerVo
  69. */
  70. @Override
  71. public void register(RegisterVo registerVo) {
  72. String nickname = registerVo.getNickname();
  73. String mobile = registerVo.getMobile();
  74. String password = registerVo.getPassword();
  75. String code = registerVo.getCode();
  76. //输入的昵称,手机号,密码,验证码都不能为空
  77. if(StringUtils.isEmpty(nickname) || StringUtils.isEmpty(mobile) ||
  78. StringUtils.isEmpty(password) || StringUtils.isEmpty(code)){
  79. throw new GuliException(20001,"注册失败:昵称,手机号,密码,验证码都不能为空");
  80. }
  81. //判断验证码
  82. //获取redis验证码
  83. String redisCode = redisTemplate.opsForValue().get(mobile);
  84. if(!code.equals(redisCode)){
  85. throw new GuliException(20001,"注册失败:验证码错误");
  86. }
  87. //判断手机号是否重复,表里面存在相同手机号不进行添加
  88. QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
  89. wrapper.eq("mobile",mobile);
  90. Integer count = baseMapper.selectCount(wrapper);
  91. if(count > 0){
  92. throw new GuliException(20001,"注册失败:手机号已经存在");
  93. }
  94. //注册信息添加到数据库
  95. UcenterMember member = new UcenterMember();
  96. member.setNickname(nickname);
  97. member.setMobile(mobile);
  98. member.setPassword(MD5.encrypt(password));
  99. member.setIsDisabled(false);//用户不禁用
  100. //头像
  101. member.setAvatar("http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132");
  102. baseMapper.insert(member);
  103. }
  104. }

结束!!!!!!!


  1. 不要相信漂亮的女人,尤其是不穿衣服的裸体女人。

发表评论

表情:
评论列表 (有 0 条评论,162人围观)

还没有评论,来说两句吧...

相关阅读

    相关 XXL-SSO 实现SSO登录

    一、 概述: 本文旨在使用XXL-SSO开源架构 实现单点登录系统。 XXL-SSO 是一个分布式单点登录框架、只需要登录一次就可以访问所有相互信任的应用系统。 拥有”