JWTutils
public class JWTUtils {
private static final String jwtToken = "123456First!@#$$";
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 * 6 * 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;
}
public static void main(String[] args) {
String token = JWTUtils.createToken(100L);
System.out.println(token);
Map<String, Object> map = JWTUtils.checkToken(token);
System.out.println(map.get("userId"));
}
}
Mapper层
LoginVo
LoginUserVo层
后续可能会使用到的userVo
LoginService
package com.yuan.service;
import com.yuan.pojo.SysUser;
import com.yuan.vo.LoginParam;
import com.yuan.vo.Result;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public interface LoginService {
/**
* 登录功能
* @param loginParam
* @return
*/
Result login(LoginParam loginParam);
SysUser checkToken(String token);
/**
* 推出登录
* @param token
* @return
*/
Result logout(String token);
/**
* 注册
* @param loginParam
* @return
*/
Result register(LoginParam loginParam);
}
LoginServiceImpl
package com.yuan.service;
import com.alibaba.fastjson.JSON;
import com.yuan.pojo.SysUser;
import com.yuan.utils.JWTUtils;
import com.yuan.vo.ErrorCode;
import com.yuan.vo.LoginParam;
import com.yuan.vo.Result;
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 {
@Autowired
private SysUserService sysUserService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
//加密字符串
private static final String slat = "xian!@#";
@Override
public Result login(LoginParam loginParam) {
/**
* 1:检查参数是否合法
* 2:根据用户名和密码 去 user表中查询 如果不存在就登录失败 存在就使用jwt 生产token 返回客户端
* 3token 放入redis当中 映射存储user的信息(token:user) 设置过期时间(登录认证时候 先认证token字符串是否合法 redis认证是否存在)
*/
String account = loginParam.getAccount();
String password = loginParam.getPassword();
if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
return Result.fail(ErrorCode.PARAMS_ERROR.getMsg(), ErrorCode.PARAMS_ERROR.getCode());
}
//这里接着SysUserServiceImpl中处理密码加密问题
password = DigestUtils.md2Hex(password + slat);
SysUser sysUser = sysUserService.findUser(account, password);
if (sysUser == null) {
return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg(), ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode());
}
String token = JWTUtils.createToken(sysUser.getId());
//
redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(sysUser), 1, TimeUnit.DAYS);
return Result.success(token);
}
@Override
public SysUser checkToken(String token) {
/**
* 1:首先token合法性校验
* 是否为空 解析是否成功 redis是否存在
* 2:如果失败返回错误
* 3:成功后返回对应结果 LoginVo
*/
if (StringUtils.isBlank(token)) {
return null;
}
Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
if (stringObjectMap == null) {
return null;
}
String userJson = redisTemplate.opsForValue().get("TOKEN_" + token);
if (StringUtils.isBlank(userJson)){
return null;
}
SysUser sysUser = JSON.parseObject(userJson, SysUser.class);
return sysUser;
}
@Override
public Result logout(String token) {
redisTemplate.delete("TOKEN_"+token);
return Result.success(null);
}
@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.TOKEN_ERROR.getMsg(), ErrorCode.TOKEN_ERROR.getCode());
}
SysUser sysUser = sysUserService.findUserByAccount(account);
//第二步骤 判断账户是否存在
if (sysUser!=null){
return Result.fail("账号已被人注册",ErrorCode.ACCOUNT_EXIST.getCode());
}
//第三步 不存在就注册 并且填充属性
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 为true
sysUser.setDeleted(0); // 0 为false
sysUser.setSalt("");
sysUser.setStatus("");
sysUser.setEmail("");
this.sysUserService.save(sysUser);
//第四步 生成token 存在redis
String token = JWTUtils.createToken(sysUser.getId());
redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser),1, TimeUnit.DAYS);
return Result.success(token);
//在添加事务 阻止注册失败时 将数据添加进数据库 进行回滚@Transactional 理论上在接口处添加LoginService
}
}
Sysuser
SysuserIService
package com.yuan.service;
import com.yuan.pojo.SysUser;
import com.yuan.vo.Result;
import com.yuan.vo.UserVo;
public interface SysUserService {
UserVo findUserVoById(Long id);
SysUser findUserById(Long id);
SysUser findUser(String account, String password);
//根据token查询用户信息
Result findUserByToken(String token);
/**
* 根据账户查找用户
* @param account
* @return
*/
SysUser findUserByAccount(String account);
/**
* 保存用户
* @param sysUser
*/
void save(SysUser sysUser);
}
SysuserIServiceImpl
package com.yuan.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yuan.mapper.SysUserMapper;
import com.yuan.pojo.SysUser;
import com.yuan.vo.ErrorCode;
import com.yuan.vo.LoginUserVo;
import com.yuan.vo.Result;
import com.yuan.vo.UserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class SysUserServiceImpl implements SysUserService {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private LoginService loginServiece;
@Override
public SysUser findUserById(Long id) {
SysUser sysUser = sysUserMapper.selectById(id);
if (sysUser==null){
sysUser= new SysUser();
sysUser.setNickname("先驱者");
}
return sysUser;
}
@Override
public UserVo findUserVoById(Long id) {
SysUser sysUser = sysUserMapper.selectById(id);
if (sysUser==null){
sysUser= new SysUser();
sysUser.setId(1L);
sysUser.setAvatar("/static/img/logo.b3a48c0.png");
sysUser.setNickname("先驱者");
}
UserVo userVo = new UserVo();
userVo.setId(String.valueOf(sysUser.getId()));//强转
BeanUtils.copyProperties(sysUser,userVo);
return userVo;
}
@Override
public SysUser findUser(String account, String password) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getAccount,account);
//password这里再数据库中实际上是加密的 这里转到loginservice中处理密码加密
queryWrapper.eq(SysUser::getPassword,password);
queryWrapper.select(SysUser::getAccount,SysUser::getAvatar,SysUser::getId,SysUser::getNickname);
queryWrapper.last("limit 1 ");
return sysUserMapper.selectOne(queryWrapper);
}
@Override
public Result findUserByToken(String token) {
SysUser sysUser = loginServiece.checkToken(token);
if (sysUser==null){
Result.fail(ErrorCode.TOKEN_ERROR.getMsg(), ErrorCode.TOKEN_ERROR.getCode());
}
LoginUserVo loginUserVo= new LoginUserVo();
loginUserVo.setAccount(sysUser.getAccount());
loginUserVo.setNickname(sysUser.getNickname());
loginUserVo.setAvatar(sysUser.getAvatar());
loginUserVo.setId(String.valueOf(sysUser.getId()));
return Result.success(loginUserVo);
}
@Override
public SysUser findUserByAccount(String account) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getAccount,account);
queryWrapper.last("limit 1");
return sysUserMapper.selectOne(queryWrapper);
}
@Override
public void save(SysUser sysUser) {
//保存用户 id会自动生成
//这个id是分布式id 采用雪花算法
sysUserMapper.insert(sysUser);
}
}