记一次实战项目所学(JWT篇)
记一次实战项目所学(JWT篇)
5. 登录验证功能
先获取公钥准备将前端输入的进行加密
//获得公钥
@GetMapping("/rsa-pks")
public JsonResponse<String> getRsaPublicKey(){
String publicKeyStr = RSAUtil.getPublicKeyStr();
return new JsonResponse<>(publicKeyStr);
}
新建(注册)一个user
(controller层)
//新建一个用户
@PostMapping("/users") //@RequestBody 把User 封装成json数据返回
public JsonResponse<String>addUser(@RequestBody User user){
userService.addUser(user);
return JsonResponse.success();
}
(Service层)
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void addUser(User user) {
String phone = user.getPhone();
if (StringUtils.isNullOrEmpty(phone)) {
throw new ConditionException("手机号不能为空!");
}
User dbUser = this.getUserByPhone(phone);
if (dbUser != null) {
throw new ConditionException("该手机号已经被注册");
}
//加密需要
Date now = new Date();
//md5需要加密
String salt = String.valueOf(now.getTime());
String password = user.getPassword();
String rawPassword;
try {
rawPassword = RSAUtil.decrypt(password);//该密码已经通过前端获取的公钥加密
} catch (Exception e) {
throw new ConditionException("解密失败");
}
String md5Password = MD5Util.sign(rawPassword, salt, "UTF-8");
user.setSalt(salt);
user.setPassword(md5Password);
user.setCreateTime(now);
userDao.addUser(user);
//添加用户信息(这里有两张表user和userinfo )
UserInfo userInfo = new UserInfo();
userInfo.setUserId(user.getId());
userInfo.setNick(UserConstant.DEFAULT_NICK);
userInfo.setBirth(UserConstant.DEFAULT_BIRTH);
userInfo.setGender(UserConstant.GENDER_FEMALE);
userInfo.setCreateTime(now);
userDao.addUserInfo(userInfo);
}
public User getUserByPhone(String phone) {
return userDao.getUserByPhone(phone);
}
dao层为数据操作不再贴代码啦
用户登录
controller
//用户登录
@PostMapping("/user-tokens")
public JsonResponse<String> login(@RequestBody User user) throws Exception{
String token=userService.login(user);
return new JsonResponse<>(token);
}
service
public String login(User user) throws Exception {
String phone = user.getPhone();
if (StringUtils.isNullOrEmpty(phone)) {
throw new ConditionException("手机号不能为空!");}
User dbUser = this.getUserByPhone(phone);
if (dbUser == null) {
throw new ConditionException("当前用户不存在");
}
String password = user.getPassword();
String rowpassword;
try {
rowpassword = RSAUtil.decrypt(password);
} catch (Exception e) {
throw new ConditionException("密码解密失败");
}
String salt = dbUser.getSalt();
String md5Password = MD5Util.sign(rowpassword, salt, "UTF-8");
if (!md5Password.equals(dbUser.getPassword())) {
throw new ConditionException("密码错误!");
}
return TokenUtil.generateToken(dbUser.getId());
}
前端加密不安全,数据库存入的密码应该是不可逆的,每次认证时候前端传入密码加密后跟后端数据库里密码比对,如果一样密码正确,如果不一样密码不正确,前端加密后传输是怕传输过程被拦截获取到明文密码
因为id是唯一的所以id可以作为token
5.5 基于JWT的用户的token验证
依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
util.token
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.imooc.bilibili.domain.except.ConditionException;
import java.util.Calendar;
import java.util.Date;
public class TokenUtil {
private static final String ISSUER="签发者"; //签发者是谁,随意填
public static String generateToken(Long userId) throws Exception{
Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
Calendar calendar =Calendar.getInstance(); //用于实现过期时间
calendar.setTime(new Date());
calendar.add(Calendar.SECOND,30); //30s过期
return JWT.create().withKeyId(String.valueOf(userId))
.withIssuer(ISSUER)
.withExpiresAt(calendar.getTime())
.sign(algorithm);
}
//解密
public static Long verifyToken(String token) {
try{
Algorithm algorithm =Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
JWTVerifier verifier =JWT.require(algorithm).build();
DecodedJWT jwt= verifier.verify(token);
String keyId = jwt.getKeyId();
return Long.valueOf(keyId);
}catch (TokenExpiredException e){
throw new ConditionException("555","token过期!");
}catch (Exception e){
throw new ConditionException("非法用户token");
}
}
}
需要一个通用方法,获取token里的userid(一般放在请求头里)
import com.imooc.bilibili.domain.except.ConditionException;
import com.imooc.bilibili.service.Util.TokenUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
@Component
public class UserSupport {
public Long getCurrentUserId(){
//抓取请求上下文,获取token(在请求头中)+
ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String token =requestAttributes.getRequest().getHeader("token");
Long userId= TokenUtil.verifyToken(token);
if(userId<0){
throw new ConditionException("非法用户!");
}
return userId;
}
}
原文地址:https://blog.csdn.net/qq_43660290/article/details/136677347
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!