com.auth0
java-jwt
3.3.0
com.alibaba
fastjson
1.2.47
cn.hutool
hutool-all
5.4.4
注意:我们默认是已经配置好mybatis的web项目,还未配置myBatis?点击此处
2.自定义两个注解
用来跳过验证的PassToken
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
需要登录才能进行操作的注解UserLoginToken
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken { boolean required() default true; }
@Target:注解的作用目标
- @Target(ElementType.TYPE)——接口、类、枚举、注解
- @Target(ElementType.FIELD)——字段、枚举的常量
- @Target(ElementType.METHOD)——方法
- @Target(ElementType.PARAMETER)——方法参数
- @Target(ElementType.CONSTRUCTOR) ——构造函数
- @Target(ElementType.LOCAL_VARIABLE)——局部变量
- @Target(ElementType.ANNOTATION_TYPE)——注解
- @Target(ElementType.PACKAGE)——包
@Retention:注解的保留位置
- RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
- RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
- RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
- @Document:说明该注解将被包含在javadoc中
- @Inherited:说明子类可以继承父类中的该注解
3.简单自定义一个实体类User
public class User implements java.io.Serializable { /** 版本号 */ private static final long serialVersionUID = 6111899065812654266L; /** 主键自增Id */ private Integer userId; /** 用户民 */ private String userName; /** 用户密码 */ private String password; /** • 获取主键自增Id • • @return 主键自增Id */ public Integer getUserId() { return this.userId; } /**
- 设置主键自增Id
- @param userId
主键自增Id • 1
*/ public void setUserId(Integer userId) { this.userId = userId; } /** • 获取用户民 • • @return 用户民 */ public String getUserName() { return this.userName; } /**
- 设置用户民
- @param userName
用户民 • 1
*/ public void setUserName(String userName) { this.userName = userName; } /** • 获取用户密码 • • @return 用户密码 */ public String getPassword() { return this.password; } /**
- 设置用户密码
- @param password
用户密码 • 1
*/ public void setPassword(String password) { this.password = password; } }
4.Mapper接口
public interface UserMapper { public List getUserSelective(User user); public User getUserByPrimary(Integer userId); public User getUserByName(String userName); }
5.service
UserService public interface UserService { /** • 通过用户名获取唯一用户 • @param userName • @return */ public User getUserByUserName(String userName); /**
- 根据条件获取用户
- @param user
• @return */ public List getUserSelective(User user); /** • 通过主键获取用户 • @param userId • @return */ public User getUserByUserId(Integer userId); }
6.service的实现类
UserServiceImpl @Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public User getUserByUserName(String userName) { User user=userMapper.getUserByName(userName); return user; } @Override public List getUserSelective(User user) { return userMapper.getUserSelective(user); } @Override public User getUserByUserId(Integer userId) { return userMapper.getUserByPrimary(userId); } }
7.UserMapper.xml
u.user_id, u.user_name, u.password SELECT FROM user u WHERE 1 = 1 AND u.user_name LIKE CONCAT(‘%’, #{userName}, ‘%’) AND u.password =#{password} SELECT FROM User as u WHERE u.user_id =#{userId} SELECT FROM User as u WHERE u.user_name =#{userName} limit 1
8.token的生成方法
TokenUtils package com.personal.indentity.utils; import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import javax.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.Date; import java.util.Map; public class TokenUtils { /** • 签名秘钥 */ private static final String SECRET = “zx12345678”; /** • 签发人 */ private static final String issuer=“zhiyi”; /** • token过期时间,单位:min */ private static final Integer expireTime=2; /** • 从header中取token • @return */ public static String getToken(){ HttpServletRequest request =WebUtils.getRequest(); String re=request.getHeader(“token”); return re; } /** • 创建token • @param json 需要放入token的参数,多个参数可以封装成json或者map • @return token */ public static String createToken(JSONObject json) { try { // 加密方式 Algorithm algorithm = Algorithm.HMAC256(SECRET); return JWT.create() .withSubject(json.toString()) .withIssuer(issuer) // 设置过期时间为60分钟后 .withExpiresAt(DateUtil.offsetMinute(new Date(), expireTime)) .withClaim(“customString”, “zhiyi”) .withArrayClaim(“customArray”, new Integer[]{1, 2, 3}) .sign(algorithm); } catch (Exception exception) { //Invalid Signing configuration / Couldn’t convert Claims. System.out.println(exception.getMessage()); return null; } } /** • 校验token合法性 • • @param token to verify. */ public static boolean verifyToken(String token) { try { Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTVerifier verifier = JWT.require(algorithm) // 验证签发人是否相同 .withIssuer(issuer) .build(); /* • 校验: • 格式校验:header.payload.signature • 加密方式校验 Header中的alg • 签名信息校验,防篡改 • 载体Payload 中公有声明字段校验 */ verifier.verify(token); return true; } catch (Exception exception) { //Invalid signature/claims exception.printStackTrace(); return false; } } /** • 解析token • • @param token to decode. */ public static void decodeToken(String token) { try { DecodedJWT jwt = JWT.decode(token); Map claims = jwt.getClaims(); Claim customStringClaim = claims.get(“customString”); Claim customArrayClaim = claims.get(“customArray”); String issuer = jwt.getIssuer(); String subject = jwt.getSubject(); System.out.println(customStringClaim.asString()); System.out.println(Arrays.toString(customArrayClaim.asArray(Integer.class))); System.out.println(issuer); System.out.println(JSONUtil.parseObj(subject).get(“userId”)); } catch (JWTDecodeException exception) { //Invalid token exception.printStackTrace(); } } public static String getUserIdByToken(String token){ DecodedJWT jwt = JWT.decode(token); Map claims = jwt.getClaims(); String subject = jwt.getSubject(); String re=JSONUtil.parseObj(subject).get(“userId”).toString(); return re; } public static void main(String[] args) { JSONObject subjectJson = new JSONObject(); subjectJson.put(“userId”, 1); subjectJson.put(“name”, “ylc”); String token = createToken(subjectJson); System.out.println(“token:” + token); System.out.println(“==============================================”); // // System.out.println(“1 min exp,now verify result:” + verifyToke(token)); // System.out.println(“==============================================”); // // System.out.println(“decode info:”); // decodeToken(token); // System.out.println(“================================================”); // System.out.println(“1 min later,verify result:”+verifyToke(“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoxLFwibmFtZVwiOlwieWxjXCJ9IiwiaXNzIjoiemhpeWkiLCJleHAiOjE2MDIzMzI2OTMsImN1c3RvbUFycmF5IjpbMSwyLDNdLCJjdXN0b21TdHJpbmciOiJ6aGl5aSJ9.v6AQ2mba8gGsHFpJ52EY4fwoN03gEDsCUUSafpPscyQ”)); // System.out.println(“================================================”); System.out.println(“userId:”+getUserIdByToken(“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoxLFwibmFtZVwiOlwieWxjXCJ9IiwiaXNzIjoiemhpeWkiLCJleHAiOjE2MDIzMzM1MjEsImN1c3RvbUFycmF5IjpbMSwyLDNdLCJjdXN0b21TdHJpbmciOiJ6aGl5aSJ9.BKU-X6Bre9kCbsCtQgwDO6UE7znqbM84xy8dH6R7AiY”)); } } WebUtils package com.dubbo.consumer.indentity.util; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class WebUtils { /** • 获取request • • @return */ public static HttpServletRequest getRequest() { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); return requestAttributes == null ? null : requestAttributes.getRequest(); } /** • 获取session • • @return */ public static HttpSession getSession() { HttpSession session = getRequest().getSession(); return session; } }
Algorithm.HMAC256():使用HS256生成token,密钥则是用户的密码,唯一密钥的话可以保存在服务端。
withAudience()存入需要保存在token的信息,这里我把用户ID存入token中
9.拦截器