SpringBoot实现基于token的登录验证
基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字符串token,返回给客户端,客户端在调用其他接口的时候,需要在请求头上带上token,来验证登录信息<br /> Demo实现代码如下:<br />(因为除登录接口外,其他接口每次都需要验证token信息,所以将验证token信息的部分放在了过滤器里面)<br />————————————————<br />版权声明:本文为CSDN博主「qq_36816062」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
1.导入JWT(JSON WEB TOKEN)依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.6.0</version></dependency>
2.Jwt工具类,包括token的生成和验证
(加密秘钥先自己随便写了一个)
package com.lzs.haiyan.utils;import io.jsonwebtoken.*;import org.springframework.stereotype.Component;import java.util.Date;import java.util.HashMap;import java.util.Map;/*** @author : liangzesheng* @Date : 2022-02-17* @Description : jwt工具类*/@Componentpublic class JwtUtils {/*** 过期时间7200s*/private static final long EXPIRE_TIME=7200*1000;/*** 加密密钥*/private static final String KEY = "haiyan";/*** 生成token* @param uuid 用户uuid* @param loginnum 用户账号* @return*/public static String createToken(String uuid,String loginnum){Map<String,Object> header = new HashMap();header.put("typ","JWT");header.put("alg","HS256");//setID:用户ID//setExpiration:token过期时间 当前时间+有效时间//setSubject:用户名//setIssuedAt:token创建时间//signWith:加密方式JwtBuilder builder = Jwts.builder().setHeader(header).setId(uuid).setExpiration(new Date(System.currentTimeMillis()+EXPIRE_TIME)).setSubject(loginnum).setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256,KEY);return builder.compact();}/*** 验证token是否有效* @param token 请求头中携带的token* @return token验证结果 2-token过期;1-token认证通过;0-token认证失败*/public static int verify(String token){Claims claims = null;try {//token过期后,会抛出ExpiredJwtException 异常,通过这个来判定token过期,claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token).getBody();}catch (ExpiredJwtException e){return 2;}//从token中获取用户id,查询该Id的用户是否存在,存在则token验证通过String uuid = claims.getId();User user = haiyanFilter.selectUserByUuId(uuid);if(user != null){return 1;}else{return 0;}return 1;}}
3.过滤器,实现filter接口
每有请求都要先经过过滤器再传入到接口方法
package com.lzs.haiyan.filter;import cn.hutool.json.JSONObject;import com.lzs.haiyan.utils.JwtUtils;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;import java.io.PrintWriter;import java.util.HashMap;import java.util.Map;/*** token鉴权 过滤器* @author : lzs* @Date : 2022-02-17* @Description :*/@Componentpublic class HaiyanFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {Map<String, String> map = new HashMap<>();String url = ((HttpServletRequest) servletRequest).getRequestURI();if (url != null) {//注册与登录请求直接放行if ("/user/login".equals(url)||"/user/regist".equals(url)) {filterChain.doFilter(servletRequest, servletResponse);return;} else {//其他请求验证tokenString token = ((HttpServletRequest) servletRequest).getHeader("token");if (token != null && token.length() > 0 && token.trim().length() > 0) {//token验证结果int verify = JwtUtils.verify(token);if (verify != 1) {//验证失败if (verify == 2) {map.put("errorMsg", "token已过期");} else if (verify == 0) {map.put("errorMsg", "用户信息验证失败");}} else if (verify == 1) {//验证成功,放行filterChain.doFilter(servletRequest, servletResponse);return;}} else {//token为空的返回map.put("errorMsg", "未携带token信息");}}JSONObject jsonObject = new JSONObject(map);servletResponse.setContentType("application/json");//设置响应的编码servletResponse.setCharacterEncoding("utf-8");//响应PrintWriter pw = servletResponse.getWriter();pw.write(jsonObject.toString());pw.flush();pw.close();}}}
