1、引入相关依赖
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.15.0</version>
</dependency>
2、创建一个工具类,用于生成和验证token
public class JwtUtils {
public static final long EXPIRE=1000*60*60*24; //token过期时间
public static final String APP_SECRET="密钥"; //密钥
/**
* 生成token
* @param id
* @param nickname 昵称
* @return
*/
public static String getJwtToken(String id,String nickname){
Algorithm algorithm=Algorithm.HMAC256(APP_SECRET);
Map<String,Object> headerClaims=new HashMap<>();
headerClaims.put("typ","JWT");
headerClaims.put("alg","HS256");
String JwtToken= JWT.create()
.withHeader(headerClaims)
.withAudience("guli-user")
.withIssuedAt(new Date())
.withExpiresAt(new Date(System.currentTimeMillis()+EXPIRE))
.withClaim("id",id)
.withClaim("nickname",nickname)
.sign(algorithm);
return JwtToken;
}
/**
* 验证token
* @param jwtToken
* @return true 验证成功
* false 验证失败
*/
public static boolean checkToken(String jwtToken){
if (ObjectUtils.isEmpty(jwtToken)){
return false;
}
Algorithm algorithm=Algorithm.HMAC256(APP_SECRET);
JWTVerifier verifier=JWT.require(algorithm).build();
try {
verifier.verify(jwtToken);
}catch (JWTVerificationException exception){
exception.printStackTrace();
return false;
}
return true;
}
/**
* 验证token
* @param request
* @return true 验证成功
* false 验证失败
*/
public static boolean checkToken(HttpServletRequest request){
String jwtToken=request.getHeader("token");
if (ObjectUtils.isEmpty(jwtToken)){
return false;
}
Algorithm algorithm=Algorithm.HMAC256(APP_SECRET);
JWTVerifier verifier=JWT.require(algorithm).build();
try {
verifier.verify(jwtToken);
}catch (JWTVerificationException exception){
exception.printStackTrace();
return false;
}
return true;
}
/**
* 通过token获取id
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request){
String jwtToken=request.getHeader("token");
if (ObjectUtils.isEmpty(jwtToken)){
return "";
}
String id = JWT.decode(jwtToken).getClaim("id").asString();
return id;
}
}
3、写登录接口,登录成功后生成token发送给客户端
@PostMapping("/login")
public R loginUser(@RequestBody UcenterMember member){
String token = memberService.login(member);
return R.ok().data("token",token);
}
@Override
public String login(UcenterMember member) {
String mobile=member.getMobile(); //手机号
String password=member.getPassword(); //密码
//判断手机号和密码是否为空
if (ObjectUtils.isEmpty(mobile) || ObjectUtils.isEmpty(password)){
throw new GuliException(20001,"登录失败");
}
QueryWrapper<UcenterMember> wrapper=new QueryWrapper<>();
wrapper.eq("mobile",mobile);
UcenterMember ucenterMember = baseMapper.selectOne(wrapper);
if (ucenterMember==null){
throw new GuliException(20001,"登录失败");
}
if (!MD5.encrypt(password).equals(ucenterMember.getPassword())){
throw new GuliException(20001,"登录失败");
}
if (ucenterMember.getIsDisabled()){
throw new GuliException(20001,"登录失败");
}
String jwtToken = JwtUtils.getJwtToken(ucenterMember.getId(), ucenterMember.getNickname());
return jwtToken;
}
其中,MD5是一个工具类,用于对密码进行加密
public final class MD5 {
public static String encrypt(String strSrc) {
try {
char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
byte[] bytes = strSrc.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!+" + e);
}
}
}
客户端发请求,需要带上token,服务端会进行解密,验证token是否正确。如果token是正确的,说明用户处于登录状态。随意伪造的token是不能被解密的,会抛出异常。
Web前端实现流程
1、登录页获取表单信息发送Ajax请求,后端获取请求数据,生成token,再将token作为响应数据发送给前端。
2、前端获取token,存入cookie,再将cookie中的token取出,作为请求头发送给后端服务器。这一步可以使用axios中的拦截器实现,每次请求都从cookie中取出token,可以先判断cookie中的token是否存在
3、后端获取token,进行解密,得到用户的id,再根据id查询数据库,得到完整的用户信息,再将用户信息发送给前端。
4、前端得到用户信息,存入cookie,然后进行页面跳转,再将cookie中的用户信息取出,在网页上进行显示。
用户退出时,只要将相关的cookie删除就可以了,再进行页面跳转或刷新,或者再将vue中的用户属性置为空。