Java通过切面实现统一处理Token设置用户信息
作者:靖节先生
这篇文章主要介绍了Java切面统一处理Token设置用户信息,常见的后端开发中,接口请求中一般前端都是先通过用户登录获取token,每次接口请求都需要在头信息中携带token信息,后端每次都需要手动处理token信息,从token信息中解析获取用户信息,需要的朋友可以参考下
1. 需求概述
常见的后端开发中,接口请求中一般前端都是先通过用户登录获取token,每次接口请求都需要在头信息中携带token信息,后端每次都需要手动处理token信息,从token信息中解析获取用户信息,因为每个接口都需要处理这些公共信息,所以可以采用切面的方式进行统一处理。
2. 解决方案
- 方案一,通过注解+切面处理请求对象 通过切面获取token信息,然后解析token信息,最后把解析后的token对应的用户信息设置到请求对象中进行统一处理。
- 方案二,通过mybatis拦截器实现动态sql拼接 实现Interceptor 接口,拦截要执行的sql语句。
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),}) public class MybatisLikeSqlInterceptor implements Interceptor {}
3. 代码实现
3.1 创建解析token
token在线解析:https://www.box3.cn/tools/jwt.html
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.0.M4</version> </dependency>
package com.jerry.market.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONUtil; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTUtil; import com.jerry.market.entity.AuthorizeTokenInfo; import com.jerry.market.entity.Response; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import java.util.Map; /** * 活动控制器 * * @author zrj * @since 2022-05-05 11:27:01 */ @Slf4j @RestController @RequestMapping("/token") @Api(tags = "TokenController", description = "Token控制器") public class TokenController { private static final String SIGN = "123456"; /** * 创建token */ @PostMapping("/create") @ApiOperation(value = "创建token") public Response<String> createToken(@RequestBody AuthorizeTokenInfo authorizeUserInfo) { if (authorizeUserInfo == null) { authorizeUserInfo = AuthorizeTokenInfo.builder() .userId("Jerry") .userName("小智呀") .tenantId("123456") .createTime(DateUtil.date().toString()) .build(); } Map<String, Object> authorizeUserInfoMap = BeanUtil.beanToMap(authorizeUserInfo); //生成token String token = JWTUtil.createToken(authorizeUserInfoMap, SIGN.getBytes()); log.info("【创建token】创建token成功,token:{}", token); return Response.success("创建token成功", token); } /** * 解析token */ @PostMapping("/parse") @ApiOperation(value = "解析token") public Response<AuthorizeTokenInfo> parseToken(@RequestParam String rightToken) { log.info("【解析token】请求参数,rightToken:{}", rightToken); //验证签名 boolean verify = JWTUtil.verify(rightToken, SIGN.getBytes()); if (!verify) { return Response.success("签名无效,请检查后重试!", null); } //解析token JWT jwt = JWTUtil.parseToken(rightToken); AuthorizeTokenInfo authorizeUserInfo = JSONUtil.toBean(jwt.getPayloads(), AuthorizeTokenInfo.class); log.info("【解析token】解析token成功,authorizeUserInfo:{}", authorizeUserInfo); return Response.success("解析token成功", authorizeUserInfo); } }
3.2 注解+切面填充参数
AutoAssemble
package com.jerry.market.config; import java.lang.annotation.*; /** * 自动填充注解 * * @author zrj * @since 2022/5/5 **/ @Documented @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface AutoAssemble { }
AutoAssembleAspect
package com.jerry.market.config; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTUtil; import com.jerry.market.entity.AuthorizeTokenInfo; import com.jerry.market.entity.BaseReqDTO; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; /** * 填充基本信息 * * @author zrj * @since 2022/5/5 **/ @Slf4j @Aspect @Order(99) @Component public class AutoAssembleAspect { // 定义切点位置 private static final String POINT_CUT = "execution(* com.jerry.market.controller..*.*(..))"; private static final String AUTHORIZATION_TOKEN = "authorizationToken"; private static final String SIGN = "123456"; /** * 定义切点位置:下面如果你在SSM中用AOP,在xml中配的就是下面 */ @Pointcut(POINT_CUT) public void pointCut() { } /** * 前置通知 * * @param joinPoint 连接点 * @throws Throwable */ @Before("pointCut()") public void before(JoinPoint joinPoint) throws Throwable { //只处理带有AutoAssemble注解的控制器 AutoAssemble autoAssemble = joinPoint.getTarget().getClass().getAnnotation(AutoAssemble.class); Object[] args = joinPoint.getArgs(); if (autoAssemble == null || args == null) { log.info("BaseRequestAssembleAspect End Because No AutoAssemble!"); return; } //处理参数 BaseReqDTO baseReqDTO = null; Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); for (Object arg : args) { if (arg instanceof BaseReqDTO) { baseReqDTO = (BaseReqDTO) arg; } } ArgumentsHandler(baseReqDTO, request, method); log.info("BaseRequestAssembleAspect Success!"); } /** * 填充用户信息 * * @param baseReqDTO 用户基础信息 * @param request HttpServletRequest * @param method 方法 * @return void */ private void ArgumentsHandler(BaseReqDTO baseReqDTO, HttpServletRequest request, Method method) { log.info("ArgumentsHandler baseReqDTO:{},request:{},method:{}", baseReqDTO, request, method); if (request != null) { //解析token String rightToken = request.getHeader(AUTHORIZATION_TOKEN); AuthorizeTokenInfo authorizeTokenInfo = parseToken(rightToken); //填充用户信息 if (authorizeTokenInfo != null) { baseReqDTO.setCreateUid(authorizeTokenInfo.getUserId()); baseReqDTO.setCreateName(authorizeTokenInfo.getUserName()); baseReqDTO.setCreateTime(DateUtil.date()); baseReqDTO.setUpdateUid(authorizeTokenInfo.getUserId()); baseReqDTO.setUpdateName(authorizeTokenInfo.getUserName()); baseReqDTO.setUpdateTime(DateUtil.date()); baseReqDTO.setTenantId(authorizeTokenInfo.getTenantId()); } else { throw new RuntimeException("鉴权失败"); } } } /** * 解析token * * @param rightToken token * @return token对象 */ private AuthorizeTokenInfo parseToken(String rightToken) { log.info("parseToken request parameter rightToken:{}", rightToken); if (StrUtil.isEmpty(rightToken)) { log.info("parseToken rightToken is null."); return null; } //验证签名 boolean verify = JWTUtil.verify(rightToken, SIGN.getBytes()); if (!verify) { log.info("parseToken verify failed,verify:{}", verify); return null; } //解析token JWT jwt = JWTUtil.parseToken(rightToken); AuthorizeTokenInfo authorizeUserInfo = JSONUtil.toBean(jwt.getPayloads(), AuthorizeTokenInfo.class); log.info("parseToken success,authorizeUserInfo:{}", authorizeUserInfo); return authorizeUserInfo; } }
BaseReqDTO
package com.jerry.market.entity; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.Date; /** * 请求对象基础类 * * @author zrj * @since 2022/5/5 **/ @Data @NoArgsConstructor @AllArgsConstructor public class BaseReqDTO implements Serializable { private static final long serialVersionUID = 8391616799399185153L; /** * 租户ID */ private String tenantId; /** * 创建人ID */ private String createUid; /** * 创建人名称 */ private String createName; /** * 创建时间 */ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; /** * 修改人ID */ private String updateUid; /** * 修改人名称 */ private String updateName; /** * 修改时间 */ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private Date updateTime; }
Activity
package com.jerry.market.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * 活动表(Activity)实体类 * * @author zrj * @since 2022-05-05 11:27:01 */ @Data @NoArgsConstructor @AllArgsConstructor public class Activity extends BaseReqDTO implements Serializable { private static final long serialVersionUID = 774583104822667002L; /** * 主键 */ private Long id; /** * 活动编码 */ private String activityCode; /** * 活动名称 */ private String activityName; /** * 是否删除(0:否 1:是) */ private Integer deleted; }
ActivityController
package com.jerry.market.controller; import com.alibaba.fastjson.JSON; import com.jerry.market.config.AutoAssemble; import com.jerry.market.entity.Activity; import com.jerry.market.service.ActivityService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import com.jerry.market.entity.Response; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; /** * 活动控制器 * * @author zrj * @since 2022-05-05 11:27:01 */ @AutoAssemble @RestController @RequestMapping("/activity") @Api(tags = "ActivityController", description = "活动控制器") public class ActivityController { /** * 服务对象 */ @Resource private ActivityService activityService; /** * 通过主键查询单条数据 * * @param activity 参数对象 * @return 单条数据 */ @ApiOperation("通过主键查询单条数据") @GetMapping("/create") public Response<Activity> get(Activity activity) { System.out.println("用户基础信息:" + JSON.toJSONString(activity)); Activity result = activityService.selectById(activity.getId()); if (result != null) { return Response.success("查询成功", result); } return Response.fail("查询失败"); } /** * 新增一条数据 * * @param activity 实体类 * @return Response对象 */ @ApiOperation("创建活动") @PostMapping("/create") public Response<Activity> create(@RequestBody Activity activity) { int result = activityService.insert(activity); if (result > 0) { return Response.success("新增成功", activity); } return Response.fail("新增失败"); } /** * 修改一条数据 * * @param activity 实体类 * @return Response对象 */ @ApiOperation("修改一条数据") @PostMapping("/update") public Response<Activity> update(@RequestBody Activity activity) { Activity result = activityService.update(activity); if (result != null) { return Response.success("修改成功", result); } return Response.fail("修改失败"); } /** * 通过实体作为筛选条件查询 * * @return Response对象 */ @ApiOperation("通过实体作为筛选条件查询") @PostMapping("/selectList") public Response<List<Activity>> selectList(Activity activity) { List<Activity> activitys = activityService.selectList(activity); if (activitys != null) { return Response.success("查询成功", activitys); } return Response.fail("查询失败"); } /** * 分页查询 * * @param start 偏移 * @param limit 条数 * @return Response对象 */ @ApiOperation("分页查询") @PostMapping("/selectPage") public Response<List<Activity>> selectPage(Integer start, Integer limit) { List<Activity> activitys = activityService.selectPage(start, limit); if (activitys != null) { return Response.success("查询成功", activitys); } return Response.fail("查询失败"); } }
4. 测试验证
到此这篇关于Java切面统一处理Token设置用户信息的文章就介绍到这了,更多相关Java处理Token设置用户信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!