io.jsonwebtoken
jjwt
0.9.0
JwtFilter 过滤器
package com.tnar.config;
import com.tnar.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author dzx
* @ClassName:
* @Description:
* @date 2019年04月23日 15:05:21
*/
public class JwtFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
String requestURI = request.getRequestURI();
System.out.println("当前请求URI路径:"+requestURI);
//如果是用户注册,登录,验证,同步操作则直接放行
if(requestURI.startsWith("/tAcctCustOperate")){
chain.doFilter(req, res);
return;
}
//请求头中需要添加authorization字段
final String authHeader = request.getHeader("authorization");
// If the Http request is OPTIONS then just return the status code 200
// which is HttpServletResponse.SC_OK in this code
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(req, res);
} else {
//authorization 的 值,需要以Bearer 开头,否则认证不通过
// Check the authorization, check if the token is started by "Bearer "
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header");
}
// Then get the JWT token from authorization
final String token = authHeader.replaceFirst("Bearer", "").trim();
try {
// Use JWT parser to check if the signature is valid with the Key "secretkey"
//final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
final Claims claims = JwtUtil.parseJWT(token);
// Add the claim to request header
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
chain.doFilter(req, res);
}
}
}
JwtConfig 配置项
package com.tnar.config;
import org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author dzx
* @ClassName:
* @Description:
* @date 2019年04月23日 14:58:30
*/
@Configuration
public class JwtConfig {
@Bean
public FilterRegistrationBean jwtFilter() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/*");
System.out.println("加载jwt过滤器完成。。。。。。。。。。。。。");
return registrationBean;
}
}
JwtUtil 工具类,生成jwttoken ,以及解析 jwtToken 获取到 用户名,密码,过期时间信息等
package com.tnar.utils;
import com.alibaba.fastjson.JSON;
import com.oracle.xmlns.internal.webservices.jaxws_databinding.JavaWsdlMappingType;
import com.tnar.exception.MyException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
public class JwtUtil {
public static final long EXPIRATION_TIME = 3600_000_000L; // 1000 hour 有效期
public static final String SECRET = "lambeter";// 密钥
//解析
public static Claims parseJWT(String jsonWebToken) {
try {
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
.parseClaimsJws(jsonWebToken).getBody();
return claims;
} catch (Exception ex) {
throw new MyException(ex.getMessage());
}
}
//和时间有关的token
public static String generateToken(Integer id, Date loginTime) {
return MD5Util.getMD5ofStr((long)id + (loginTime == null ? 0L : Math.round(loginTime.getTime()/1000.0)) + SECRET);
}
//生成
public static String createJWT(String userName, String password) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//当前时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//生成签名密钥
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
//添加构成JWT的参数
JwtBuilder builder = Jwts.builder().setHeaderParam("type", "JWT")
.claim("userName", userName)
.claim("password", password)
.signWith(signatureAlgorithm, signingKey);
//添加Token过期时间
long expMillis = nowMillis + EXPIRATION_TIME;
Date exp = new Date(expMillis);
builder.setExpiration(exp).setNotBefore(now);
//生成JWT
String jwtTokenStr = builder.compact();
return jwtTokenStr;
}
public static void main(String[] args){
String token = JwtUtil.createJWT("admin", "123456");
System.out.println(token);
Claims claims = JwtUtil.parseJWT(token);
System.out.println(JSON.toJSONString(claims));
}
}
项目启动成功之后,访问 除了 /tAcctCustOperate/** 之外的其它任意接口,发现都会报以下错误,说明请求头中没有
jwtToken
然后我们 在登录的 时候 利用jwtUtil 生成 一个token
String jwtToken = JwtUtil.createJWT(userName,password);
之后将 token 返回 给 前端,前端下次在请求接口的时候,在 请求头中带上以下信息就可以通过认证,并成功访问接口了。
key 为 authorization ,value 为 Bearer(接一个空格) 开头的在登录的时候生成的jwtToken,过期时间为1000小时