springBoot集成token认证,最全Java面试知识点梳理

简介: springBoot集成token认证,最全Java面试知识点梳理

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.拦截器

相关文章
|
10月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
515 1
|
7月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
9月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
598 0
|
9月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
393 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
7月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
10月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
269 5
|
10月前
|
安全 Java API
2025 年 Java 校招面试常见问题及详细答案汇总
本资料涵盖Java校招常见面试题,包括Java基础、并发编程、JVM、Spring框架、分布式与微服务等核心知识点,并提供详细解析与实操代码,助力2025校招备战。
442 1
|
9月前
|
缓存 Java 关系型数据库
Java 面试经验总结与最新 BAT 面试资料整理含核心考点的 Java 面试经验及最新 BAT 面试资料
本文汇总了Java面试经验与BAT等大厂常见面试考点,涵盖心态准备、简历优化、面试技巧及Java基础、多线程、JVM、数据库、框架等核心技术点,并附实际代码示例,助力高效备战Java面试。
342 0
|
9月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
945 0