五、登录和注册

1、登录

1.1接口说明

接口url:/login

请求方式:POST

请求参数:

参数名称 参数类型 说明
account string 账号
password string 密码

返回数据:

{"success": true,"code": 200,"msg": "success","data": "token"
}

1.2 JWT

登录使用JWT技术。

jwt 可以生成 一个加密的token,做为用户登录的令牌,当用户登录成功之后,发放给客户端。

请求需要登录的资源或者接口的时候,将token携带,后端验证token是否合法。

jwt 有三部分组成:A.B.C

A:Header,{“type”:“JWT”,“alg”:“HS256”} 固定

B:playload,存放信息,比如,用户id,过期时间等等,可以被解密,不能存放敏感信息

C: 签证,A和B加上秘钥 加密而成,只要秘钥不丢失,可以认为是安全的。

jwt 验证,主要就是验证C部分 是否合法。

依赖包:

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

工具类:

package com.mszlu.blog.utils;import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JWTUtils {private static final String jwtToken = "123456Mszlu!@#$$";public static String createToken(Long userId){Map<String,Object> claims = new HashMap<>();claims.put("userId",userId);JwtBuilder jwtBuilder = Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtToken) // 签发算法,秘钥为jwtToken.setClaims(claims) // body数据,要唯一,自行设置.setIssuedAt(new Date()) // 设置签发时间.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000));// 一天的有效时间String token = jwtBuilder.compact();return token;}public static Map<String, Object> checkToken(String token){try {Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);return (Map<String, Object>) parse.getBody();}catch (Exception e){e.printStackTrace();}return null;}}

1.3 controller

package com.ling.blog.controller;import com.ling.blog.service.LoginService;
import com.ling.blog.vo.Result;
import com.ling.blog.vo.params.LoginParam;
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;@RestController
@RequestMapping("/login")
public class LoginController {@Autowiredprivate LoginService loginService;@PostMappingpublic Result login(@RequestBody LoginParam loginParam){return loginService.login(loginParam);}
}

1.4 service

package com.ling.blog.service;import com.ling.blog.dao.pojo.SysUser;
import com.ling.blog.vo.Result;
import com.ling.blog.vo.params.LoginParam;public interface LoginService {/*** 登录功能* @param loginParam* @return*/Result login(LoginParam loginParam);
package com.ling.blog.service.impl;import com.alibaba.fastjson.JSON;
import com.ling.blog.dao.pojo.SysUser;
import com.ling.blog.service.LoginService;
import com.ling.blog.service.SysUserService;
import com.ling.blog.utils.JWTUtils;
import com.ling.blog.vo.ErrorCode;
import com.ling.blog.vo.Result;
import com.ling.blog.vo.params.LoginParam;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.Map;
import java.util.concurrent.TimeUnit;@Service
@Transactional
public class LoginServiceImpl implements LoginService {@Autowiredprivate SysUserService sysUserService;@Autowiredprivate RedisTemplate<String,String> redisTemplate;private static final String slat = "mszlu!@#";@Overridepublic Result login(LoginParam loginParam) {//1、检测参数是否合法String account = loginParam.getAccount();String password = loginParam.getPassword();if(StringUtils.isBlank(account) || StringUtils.isBlank(password)){return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());}//密码经过处理,使用加密盐password = DigestUtils.md5Hex(password + slat);//2、根据用户名和密码去user表中查询是否存在SysUser sysUser = sysUserService.findUser(account,password);//3、如果不存在,登录失败if(sysUser == null){return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(),ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());}//4、存在,使用jwt生成token,返回给前端String token = JWTUtils.createToken(sysUser.getId());//5、token放入redis中,redis存储token:user信息 设置过期时间redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser),1, TimeUnit.DAYS);// (登陆认证时,先认证token字符串是否合法,去redis认证是否存在)return Result.success(token);}
}

md5加密的依赖包:

  <dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId></dependency>

SysUserServiceImpl:

@Override
public SysUser findUser(String account, String password) {LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(SysUser::getAccount,account);queryWrapper.eq(SysUser::getPassword,password);queryWrapper.select(SysUser::getAccount,SysUser::getId,SysUser::getAvatar,SysUser::getNickname);queryWrapper.last("limit 1");return sysUserMapper.selectOne(queryWrapper);
}

1.5 vo

package com.ling.blog.vo.params;import lombok.Data;@Data
public class LoginParam {private String account;private String password;
}

配置redis

spring.redis.host=localhost
spring.redis.port=6379
package com.mszlu.blog.vo;public enum  ErrorCode {PARAMS_ERROR(10001,"参数有误"),ACCOUNT_PWD_NOT_EXIST(10002,"用户名或密码不存在"),NO_PERMISSION(70001,"无访问权限"),SESSION_TIME_OUT(90001,"会话超时"),NO_LOGIN(90002,"未登录"),;private int code;private String msg;ErrorCode(int code, String msg){this.code = code;this.msg = msg;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

2、获取登录用户数据

2.1 接口说明

接口url:/users/currentUser

请求方式:GET

请求参数:

参数名称 参数类型 说明
Authorization string 头部信息(TOKEN)

返回数据:

{"success": true,"code": 200,"msg": "success","data": {"id":1,"account":"1","nickaname":"1","avatar":"ss"}
}

2.2 controller

package com.ling.blog.controller;import com.ling.blog.service.SysUserService;
import com.ling.blog.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate SysUserService sysUserService;@GetMapping("/currentUser")public Result currentUser(@RequestHeader("Authorization") String token){return sysUserService.findUserByToken(token);}
}

2.3 service

@Override
public Result findUserByToken(String token) {/*** 1、token合法性校验* 是否为空,解析是否成功 redis是否存在* 2、如果校验失败,返回错误* 3、如果成功,返回对应结果 LoginUserVo*/SysUser sysUser = loginService.checkToken(token);if(sysUser == null){return Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());}LoginUserVo loginUserVo = new LoginUserVo();loginUserVo.setId(sysUser.getId());loginUserVo.setNickname(sysUser.getNickname());loginUserVo.setAccount(sysUser.getAccount());loginUserVo.setAvatar(sysUser.getAvatar());return Result.success(loginUserVo);
}

2.4 vo

package com.ling.blog.vo;import lombok.Data;@Data
public class LoginUserVo {private Long id;private String account;private String nickname;private String avatar;
}

3 退出登录

3.1 接口说明

接口url:/logout

请求方式:GET

请求参数:

参数名称 参数类型 说明
Authorization string 头部信息(TOKEN)

返回数据:

{"success": true,"code": 200,"msg": "success","data": null
}

3.2 controller

package com.ling.blog.controller;import com.ling.blog.service.LoginService;
import com.ling.blog.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/logout")
public class LogoutController {@Autowiredprivate LoginService loginService;@GetMappingpublic Result logout(@RequestHeader("Authorization") String token){return loginService.logout(token);}
}

3.3 service

/*** 退出登录* @param token* @return*/
@Override
public Result logout(String token) {redisTemplate.delete("TOKEN_"+token);return Result.success(null);
}

4、注册

4.1 接口说明

接口url:/register

请求方式:POST

请求参数:

参数名称 参数类型 说明
account string 账号
password string 密码
nickname string 昵称

返回数据:

{"success": true,"code": 200,"msg": "success","data": "token"
}

4.2 controller

package com.ling.blog.controller;import com.ling.blog.service.LoginService;
import com.ling.blog.vo.Result;
import com.ling.blog.vo.params.LoginParam;
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;@RestController
@RequestMapping("/register")
public class RegisterController {@Autowiredprivate LoginService loginService;@PostMappingpublic Result register(@RequestBody LoginParam loginParam){//sso 单点登录,后期如果把登录注册功能提出去(单独的服务,可以提供独立接口的服务)return loginService.register(loginParam);}
}

参数LoginParam中 添加新的参数nickname。

4.3 service

/*** 注册功能* @param loginParam* @return*/
@Override
public Result register(LoginParam loginParam) {/*** 1、判断参数是否合法* 2、判断账户是否存在 存在,返回账户已经被注册* 3、不存在,注册用户* 4、生成token* 5、存入redis并返回* 6、注意,加上事务,一旦中间的任何过程出现问题,需要回滚*/String account = loginParam.getAccount();String password = loginParam.getPassword();String nickname = loginParam.getNickname();if(StringUtils.isBlank(account) || StringUtils.isBlank(password) || StringUtils.isBlank(nickname)){return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());}SysUser sysUser = sysUserService.findUserByAccount(account);if(sysUser != null){return Result.fail(ErrorCode.ACCOUNT_EXIST.getCode(), ErrorCode.ACCOUNT_EXIST.getMsg());}sysUser = new SysUser();sysUser.setNickname(nickname);sysUser.setAccount(account);sysUser.setPassword(DigestUtils.md5Hex(password+slat));sysUser.setCreateDate(System.currentTimeMillis());sysUser.setLastLogin(System.currentTimeMillis());sysUser.setAvatar("/static/img/logo.b3a48c0.png");sysUser.setAdmin(1); //1 为truesysUser.setDeleted(0); // 0 为falsesysUser.setId(null);sysUser.setMobilePhoneNumber("111");sysUser.setSalt("111");sysUser.setStatus("111");sysUser.setEmail("111");this.sysUserService.save(sysUser);String token = JWTUtils.createToken(sysUser.getId());//注册好像不可以设置过期时间redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser));return Result.success(token);
}

ErrorCode中添加:

ACCOUNT_EXIST(10004,"账号已存在"),

SysUserServiceImpl:

/*** 根据账户查询用户* @param account* @return*/
@Override
public SysUser findUserByAccount(String account) {/*LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(SysUser::getAccount,account);queryWrapper.last("limit 1");return sysUserMapper.selectOne(queryWrapper);*/return sysUserMapper.findUserByAccount(account);
}@Override
public void save(SysUser sysUser) {//保存用户,id会自动生成//默认生成的id是分布式id,采用雪花算法//this.sysUserMapper.insert(sysUser);// String account = sysUser.getAccount();sysUserMapper.addUser(sysUser);
}

4.4 dao

/*** 根据账户名查询用户* @param account* @return*/
SysUser findUserByAccount(@Param("account")String account);/*** 添加用户,用于注册用户的保存* @param sysUser*/
void addUser(@Param("sysUser") SysUser sysUser);
<!--SysUser findUserByAccount(@Param("account")String account);-->
<select id="findUserByAccount" parameterType="string" resultType="com.ling.blog.dao.pojo.SysUser">select *from ms_sys_user where account = #{account}
</select><!--void addUser(SysUser sysUser);-->
<insert id="addUser">insert into ms_sys_uservalues (null,#{sysUser.account},#{sysUser.admin},#{sysUser.avatar},#{sysUser.createDate},#{sysUser.deleted},#{sysUser.email},#{sysUser.lastLogin},#{sysUser.mobilePhoneNumber},#{sysUser.nickname},#{sysUser.password},#{sysUser.salt},#{sysUser.status})
</insert>

4.5加事务

@Service
@Transactional
public class LoginServiceImpl implements LoginService {}

个人博客项目——登录和注册相关推荐

  1. 博客项目——登录功能实现

    客户端(login.art) 登录功能实现,表单要添加name属性,这样才能向服务器提交数据 <div class="login-body"><div class ...

  2. 博客项目学习笔记十二:登录注册功能(登录)

    博客项目目录: 请戳这里 准备 需求:实现用户登录功能,登录之后,跳转到首页,并且页面信息由游客状态变为用户状态 1.引入shiro依赖包 <dependency><groupId& ...

  3. 简单个人博客系统java web_JavaWeb个人博客项目:手把手教你实现博客后台系统之登录与注册...

    JavaWeb个人博客项目:手把手教你实现博客后台系统之登录与注册 发布时间:2020-07-17 17:10阅读:( )字号: 大 中 小 后台系统的所有界面图以及之前的准备工作欢迎看我之前的博文& ...

  4. 项目分享:模拟博客园登录

    项目二:模拟博客园登录 声明: 项目代码纯粹本人自己编写,无任何抄袭.转载等情况,所以写的很low,仅供大家参考,有不懂的随时评论留言 项目要求: 首先程序启动,显示下面内容供用户选择: 请登录 请注 ...

  5. 【博客项目】—登录验证功能实现( 五)

    [博客项目]-登录验证功能实现( 五)

  6. 【博客项目】—登录功能实现( 四)

    [博客项目]-登录功能实现( 四) 创建用户集合,初始化用户 连接数据库 创建用户集合 初始化项目

  7. 【EduCoder答案】博客系统 - 登录注册界面

    简介 答案查询的入口网页版 其他各类实训答案的目录见这里 答案获取的方法简介见这里 并不是所有的关卡都有答案,有些只有部分关卡有 不要直接复制答案哦 博客系统 - 登录注册界面 >>> ...

  8. Django之BBS博客项目

    一.登陆功能(验证码) 1 from geetest importGeetestLib2 from django.contrib importauth3 4 #使用极验滑动验证码的登陆 5 deflo ...

  9. 码神之路博客项目构建记录

    个人博客项目 Blog 一.项目搭建(2021.10.6) pom文件导入相关依赖 application配置文件配置 Mybatis Plus配置 跨域问题解决 二.首页配置 首页分页显示文章信息 ...

  10. Django day17 博客项目(一)

    一: 博客项目需求分析 首页(显示文章) 文章详情 点赞, 点踩 文章评论 字评论 评论的展示 登录功能(图片验证码) 注册功能(基于form验证,ajax) 个人站点(不同人不同样式,文章过滤) 后 ...

最新文章

  1. 也议GetLastKnownLocation!!(独家理解)
  2. 2020最后一个月,近4成应届生未就业,19个头部城市谁最留不住人?
  3. 如何测试一个网页登陆界面
  4. ASP.NET文件操作收藏
  5. 使用SecureCRT录制自动脚本
  6. 腾讯携手2020全球C++及系统软件技术大会
  7. hadoop历史版本,包括大名鼎鼎的hadoop 0.20.2
  8. arcgis两点之间连线_使用ArcGIS制作城市关系强度图(附数据下载)
  9. int 为什么是2147483647_现在的C语言编辑器里的int范围为什么是-2147483648~2147483647...
  10. MATLAB遍历文件夹
  11. vscode设置eclipse快捷键
  12. uniapp运行到微信小程序开发工具
  13. 两个计算机怎么共享一台打印机共享,两台电脑如何共享打印机 多台电脑共享一台打印机设置方法【详细教程】...
  14. 不变初心数——python
  15. HALO博客配置华为云OSS上传附件
  16. Cadence每日一学_11 | OrCAD原理图DRC检查、BOM表导出、PDF导出、网表导出
  17. 无人驾驶仿真软件PanoSim:(1)介绍
  18. sip 协议注册流程
  19. python @ 用法
  20. 201571030121《小学四则运算练习软件软件需求说明》结对项目报告

热门文章

  1. ArcGIS不同坡度植被覆盖率分析步骤
  2. 武汉大学计算机学院csc,2018年春武汉大学CSC公派出国留学录取名单
  3. 2022年基于PXI/PCI/PCIe/USB总线的高速数据采集卡汇总
  4. MATLAB与STK互联39:动画控制、地面两个点的大圆距离计算
  5. 域名申请/ssl证书申请
  6. Android开发之科大讯飞语音合成与播报
  7. c8500刷机 转帖
  8. 中报行情 锁定四大板块8只高送转潜力股 2011-7-9
  9. 最新最全的阿里云产品手册出炉
  10. CodeForces703D Mishka and Interesting sum(树状数组)