如果写某些接口 需要身份验证 jwt 简单 方便 那么就来分享一下
AOP 实现的身份验证
首先 maven引入关联jar
<!-- api token web server -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
创建jwt工具类
package io.nutz.nutzsite.common.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.nutz.mvc.Mvcs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Key;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* jwt验证工具类
* @author Hamming_Yu on 2018/11/13.
*/
public class JWTUtil {
private static Logger log = LoggerFactory.getLogger(JWTUtil.class);
//We will sign our JWT with our ApiKey secret
private static Key key;
private static String issuer="nutzsite";
static {
//初始化api.key 文件存放位置
Path fpath= Paths.get("api.key");
//创建文件
if(!Files.exists(fpath)) {
try {
Files.createFile(fpath);
// Files.createDirectory(fpath);
key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
try ( ObjectOutputStream keyOut = new ObjectOutputStream(new FileOutputStream(fpath.toFile()))){
keyOut.writeObject(key);
keyOut.close();
} catch (IOException e) {
log.debug(e.getMessage());
}
} catch (IOException e) {
e.printStackTrace();
}
}else {
try (ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(fpath.toFile()))){
key = (Key) keyIn.readObject();
keyIn.close();
} catch (IOException e) {
log.debug(e.getMessage());
} catch (ClassNotFoundException e) {
log.debug(e.getMessage());
}
}
}
/**
* 创建token
* @param id
* @return
*/
public static String createJWT(String id) {
//过期时间不要太长 移动端需要长时间记住用户名 让移动端本地存储 用户名 密码即可
Date exp = DateUtils.addDays(new Date(),1) ;
//Let's set the JWT Claims
JwtBuilder builder = Jwts.builder().setId(id)
.setIssuedAt(new Date())
.setSubject(id)
.setIssuer(issuer)
.signWith(key);
builder.setExpiration(exp);
//Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}
/**
* 验证token
* @param token
* @return
*/
public static boolean verifyToken(String token) {
try {
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token).getBody();
if(!issuer.equals(claims.getIssuer()) &&
!claims.getIssuer().equals( claims.getSubject() ) ){
return false;
}
return true;
} catch (Exception e) {
log.debug(e.getMessage());
// e.printStackTrace();
return false;
}
}
/**
* 获取ID
* @return
*/
public static String getId() {
HttpServletRequest request = Mvcs.getReq();
Map<String, String> map = new HashMap<String, String>();
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
try{
String token=map.get("authorization");
if(verifyToken(token)){
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token).getBody();
return claims.getId();
}
}catch (Exception e){
log.debug(e.getMessage());
e.printStackTrace();
}
return null;
}
/**
* Sample method to validate and read the JWT
* @param jwt
*/
public static void parseJWT(String jwt) {
//This line will throw an exception if it is not a signed JWS (as expected)
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwt).getBody();
// System.out.println("ID: " + claims.getId());
// System.out.println("Subject: " + claims.getSubject());
// System.out.println("Issuer: " + claims.getIssuer());
// System.out.println("Expiration: " + claims.getExpiration());
}
}
自定义注解
package io.nutz.nutzsite.common.annotation;
import java.lang.annotation.*;
/**
* @Author: Haimming
* @Date: 2019-05-17 16:52
* @Version 1.0
*/
// 必须带这个,不然读取不到的
@Retention(RetentionPolicy.RUNTIME)
// aop,一般指方法
@Target({ElementType.METHOD})
// 记录到javadoc
@Documented
public @interface AccessToken {
}
AOP 实现
package io.nutz.nutzsite.common.aop;
import io.nutz.nutzsite.common.annotation.AccessToken;
import org.nutz.aop.MethodInterceptor;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.aop.SimpleAopMaker;
import org.nutz.ioc.loader.annotation.IocBean;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
/**
* @Author: Haimming
* @Date: 2019-05-17 16:53
* @Version 1.0
*/
@IocBean(name="$aop_access_token")
public class AccessTokenAopConfigration extends SimpleAopMaker<AccessToken> {
@Override
public List<? extends MethodInterceptor> makeIt(AccessToken accessToken, Method method, Ioc ioc) {
return Arrays.asList(new AccessTokenAopInterceptor(ioc, accessToken, method));
}
}
package io.nutz.nutzsite.common.aop;
import io.nutz.nutzsite.common.annotation.AccessToken;
import io.nutz.nutzsite.common.base.Result;
import io.nutz.nutzsite.common.utils.JWTUtil;
import org.nutz.aop.InterceptorChain;
import org.nutz.aop.MethodInterceptor;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;
import java.lang.reflect.Method;
/**
* @Author: Haimming
* @Date: 2019-05-17 16:57
* @Version 1.0
*/
@IocBean
public class AccessTokenAopInterceptor implements MethodInterceptor {
private static final Log log = Logs.get();
protected Ioc ioc;
public AccessTokenAopInterceptor(Ioc ioc, AccessToken token, Method method) {
this.ioc = ioc;
}
/**
* 过滤器 验证登录
* @param chain
* @throws Throwable
*/
@Override
public void filter(InterceptorChain chain) throws Throwable {
try {
String token = Strings.sNull(Mvcs.getReq().getHeader("authorization"));
if (JWTUtil.verifyToken(token)) {
chain.doChain();
}else {
Mvcs.SKIP_COMMITTED =true;
Mvcs.write(Mvcs.getResp(), Result.token(), JsonFormat.full());
}
} catch (Throwable e) {
log.debug("aop.error", e);
throw e;
}
}
}
package io.nutz.nutzsite.common.base;
import org.nutz.lang.Strings;
import org.nutz.mvc.Mvcs;
/**
* 返回消息通用类
* "result": 1,【4种状态,0:请求成功,1:请求失败,2: ,3:token失效】--类型为Integer
* "msg": "相关内容解释",
* "data": "数据主体"
* @author wizzer
* @date 2016/6/22
*/
public class Result {
private int code;
private String msg;
private Object data;
public Result() {
}
public Result(int code, String msg, Object data) {
this.code = code;
this.msg = Strings.isBlank(msg) ? "" : Mvcs.getMessage(Mvcs.getActionContext().getRequest(), msg);
this.data = data;
}
public static Result success(String content) {
return new Result(0, content, null);
}
public static Result success(String content, Object data) {
return new Result(0, content, data);
}
public static Result error(int code, String content) {
return new Result(code, content, null);
}
public static Result error(String content) {
return new Result(1, content, null);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return this.msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result token() {
return new Result(3, "token失效", null);
}
}
验证 是否有效 需要身份验证方法添加注解@AccessToken
@GET
@ApiOperation(value = "心跳接口", notes = "发我一个ping,回你一个pong", httpMethod="GET")
@At
@Ok("json:full")
@AccessToken
public Object ping() {
return new NutMap("ok", true).setv("data", "pong");
}
请求headers添加
authorization 即可正常访问