流程: 1.建立token工具类,先编辑token签名sign():设置超时时长、token秘钥。 2.配置拦截器类,拦截器中重写prehandle()方法,对每次请求进行自定义的拦截操作。 3.建立配置类:定义拦截与不拦截的接口信息。
页面请求登录接口→登录成功后,返回登录信息 token秘钥给前端→前端记住密钥信息,并赋予每个接口(例:在每个接口访问时将秘钥信息放置于headers中的参数下)→拦截器接到请求,从headers获取token密钥进行匹配,通过则继续访问,不通过则返回提示信息。
1..建立token工具类,先编辑token签名sign():设置超时时长、token秘钥。
import com.auth0.jwt.jwt; import com.auth0.jwt.jwtverifier; import com.auth0.jwt.algorithms.algorithm; import lombok.extern.slf4j.slf4j; import java.io.unsupportedencodingexception; import java.util.date; import java.util.hashmap; import java.util.map; @slf4j public class jwtutil { /** * 过期时间 */ private static final long expire_time = 15 * 60 * 1000; /** * token秘钥 */ private static final string token_secret = "c369a1e4-43ee-4e1e-b130-2b952f1ba9ad"; /** * 签名方法 * @param username username * @param role role * @return string role */ public static string sign(string username, string role) { log.info("sign begin."); try { // 过期时间 date date = new date(system.currenttimemillis() expire_time); // 秘钥和加密算法 algorithm algorithm = algorithm.hmac256(token_secret); // headers mapherders = new hashmap<>(2); herders.put("typ", "jwt"); herders.put("alg", "hs256"); log.info("sign end."); return jwt.create() .withheader(herders) .withclaim("username", username) .withclaim("role", role) .withexpiresat(date) .sign(algorithm); } catch (unsupportedencodingexception exception) { exception.printstacktrace(); log.info("sign error."); return exception.getmessage(); } } /** * token 校验方法 * @param username username * @return string role */ public static boolean verify(string token) { log.info("verify begin."); try { algorithm algorithm = algorithm.hmac256(token_secret); jwtverifier verifier = jwt.require(algorithm).build(); verifier.verify(token); log.info("verify end."); return true; } catch (unsupportedencodingexception exception) { log.info("verify error."); exception.printstacktrace(); return false; } } }
2.controller层登录操作中设置登录校验及token插入:
/** * @program: smartoperationtest * @description: 用户操作 * @author: 作者名字 * @create: 2021-07-15 10:37 **/ @controller @requestmapping("/user") @api("useractioncontroller") @crossorigin(value = "*", maxage = 3600) @slf4j public class useractioncontroller { @autowired userinfoserviceimpl userinfoservice; @requestmapping(value = "/login", method = requestmethod.get) @apioperation(value = "登录", notes = "") @responsebody public commonresultbo userlogin(@requestparam() string username, @requestparam() string password) { commonresultbo resultbo = userinfoservice.getuserinfo(username, password); integer statuscode = resultbo.getstatuscode(); if (statuscode == 200) {// 登录校验通过则插入token信息 userinfo userinfo = (userinfo)resultbo.getdata(); string token = jwtutil.sign(username, userinfo.getrole()); resultbo.setdata(token); return resultbo; } resultbo.setdata(""); resultbo.setstatuscode(1); resultbo.setstatusmessage("token failed"); return resultbo; } }
3.设置拦截器
import com.alibaba.fastjson.jsonobject;
import lombok.extern.slf4j.slf4j;
import org.springframework.stereotype.component;
import org.springframework.web.servlet.handlerinterceptor;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import java.io.ioexception;
/**
* @program: smartoperationtest
* @description: 拦截器
* @author: 作者名字
* @create: 2021-07-15 16:20
**/
@component
@slf4j
public class tokeninterceptor implements handlerinterceptor {
public boolean prehandle(httpservletrequest request, httpservletresponse response, object object) throws ioexception {
log.info("prehandle begin.");
response.setcharacterencoding("utf-8");
string token = request.getheader("accesstoken");
log.info("prehandle begin token: {}." token);
// token通过验证 返回true 继续访问
if (null != token) {
boolean result = jwtutil.verify(token) ;
if (result) {
log.info("prehandle end.");
return true;
}
}
// token验证不通过 返回失败提示
commonresultbo commonresultbo = commonresultbo.init(null, -1, "failed", "token invalid");
response.getwriter().write(jsonobject.tojsonstring(commonresultbo));
log.info("prehandle end.");
return false;
}
}
4.建立配置类,明确拦截与不拦截的接口:/*拦截一层路径,/**拦截/后全布路径。
import com.hawk.smartoperationtest.common.tokeninterceptor; import lombok.extern.slf4j.slf4j; import org.springframework.beans.factory.annotation.autowired; import org.springframework.context.annotation.configuration; import org.springframework.web.servlet.config.annotation.*; /** * @program: smartoperationtest * @description: 自定义拦截器配置 * @author: 作者名字 * @create: 2021-07-15 16:48 **/ @configuration @slf4j public class mvcconfig extends webmvcconfigurationsupport { @autowired tokeninterceptor tokeninterceptor; @override protected void addinterceptors(interceptorregistry registry) { //添加自定义拦截器 log.info("addinterceptors begin."); interceptorregistration patterns = registry.addinterceptor(tokeninterceptor).addpathpatterns("/mary/**") //指定拦截的url地址 .excludepathpatterns("/user/**", "/swagger-resources/**", "/v2/**"); log.info("addinterceptors :" patterns.tostring()); } /** * 发现如果继承了webmvcconfigurationsupport,则在yml中配置的相关内容会失效。 * 配置拦截器后swagger访问会被拦截 按如下配置可保持swagger访问 * 需要重新指定静态资源 * @param registry */ @override public void addresourcehandlers(resourcehandlerregistry registry) { // registry.addresourcehandler("/**").addresourcelocations("classpath:/static/"); registry.addresourcehandler("swagger-ui.html") .addresourcelocations("classpath:/meta-inf/resources/"); registry.addresourcehandler("/webjars/**") .addresourcelocations("classpath:/meta-inf/resources/webjars/"); // super.addresourcehandlers(registry); } }
登录验证通过后,再次进行接口访问时,header中就要携带token信息进行校验。例:
accesstoken:xxxtoken加密信息xxxx
verify()也可以用于任意地方进行token校验。
解析token:例
decodedjwt verify = verifier.verify(token); string role = verify.getclaim("role").asstring();