Java通過(guò)切面實(shí)現(xiàn)統(tǒng)一處理Token設(shè)置用戶信息
1. 需求概述
常見(jiàn)的后端開(kāi)發(fā)中,接口請(qǐng)求中一般前端都是先通過(guò)用戶登錄獲取token,每次接口請(qǐng)求都需要在頭信息中攜帶token信息,后端每次都需要手動(dòng)處理token信息,從token信息中解析獲取用戶信息,因?yàn)槊總€(gè)接口都需要處理這些公共信息,所以可以采用切面的方式進(jìn)行統(tǒng)一處理。
2. 解決方案
- 方案一,通過(guò)注解+切面處理請(qǐng)求對(duì)象 通過(guò)切面獲取token信息,然后解析token信息,最后把解析后的token對(duì)應(yīng)的用戶信息設(shè)置到請(qǐng)求對(duì)象中進(jìn)行統(tǒng)一處理。
- 方案二,通過(guò)mybatis攔截器實(shí)現(xiàn)動(dòng)態(tài)sql拼接 實(shí)現(xiàn)Interceptor 接口,攔截要執(zhí)行的sql語(yǔ)句。
@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. 代碼實(shí)現(xiàn)
3.1 創(chuàng)建解析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;
/**
* 活動(dòng)控制器
*
* @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";
/**
* 創(chuàng)建token
*/
@PostMapping("/create")
@ApiOperation(value = "創(chuàng)建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("【創(chuàng)建token】創(chuàng)建token成功,token:{}", token);
return Response.success("創(chuàng)建token成功", token);
}
/**
* 解析token
*/
@PostMapping("/parse")
@ApiOperation(value = "解析token")
public Response<AuthorizeTokenInfo> parseToken(@RequestParam String rightToken) {
log.info("【解析token】請(qǐng)求參數(shù),rightToken:{}", rightToken);
//驗(yàn)證簽名
boolean verify = JWTUtil.verify(rightToken, SIGN.getBytes());
if (!verify) {
return Response.success("簽名無(wú)效,請(qǐng)檢查后重試!", 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 注解+切面填充參數(shù)
AutoAssemble
package com.jerry.market.config;
import java.lang.annotation.*;
/**
* 自動(dòng)填充注解
*
* @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 {
// 定義切點(diǎn)位置
private static final String POINT_CUT = "execution(* com.jerry.market.controller..*.*(..))";
private static final String AUTHORIZATION_TOKEN = "authorizationToken";
private static final String SIGN = "123456";
/**
* 定義切點(diǎn)位置:下面如果你在SSM中用AOP,在xml中配的就是下面
*/
@Pointcut(POINT_CUT)
public void pointCut() {
}
/**
* 前置通知
*
* @param joinPoint 連接點(diǎn)
* @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;
}
//處理參數(shù)
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 用戶基礎(chǔ)信息
* @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("鑒權(quán)失敗");
}
}
}
/**
* 解析token
*
* @param rightToken token
* @return token對(duì)象
*/
private AuthorizeTokenInfo parseToken(String rightToken) {
log.info("parseToken request parameter rightToken:{}", rightToken);
if (StrUtil.isEmpty(rightToken)) {
log.info("parseToken rightToken is null.");
return null;
}
//驗(yàn)證簽名
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;
/**
* 請(qǐng)求對(duì)象基礎(chǔ)類(lèi)
*
* @author zrj
* @since 2022/5/5
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseReqDTO implements Serializable {
private static final long serialVersionUID = 8391616799399185153L;
/**
* 租戶ID
*/
private String tenantId;
/**
* 創(chuàng)建人ID
*/
private String createUid;
/**
* 創(chuàng)建人名稱(chēng)
*/
private String createName;
/**
* 創(chuàng)建時(shí)間
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 修改人ID
*/
private String updateUid;
/**
* 修改人名稱(chēng)
*/
private String updateName;
/**
* 修改時(shí)間
*/
@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;
/**
* 活動(dòng)表(Activity)實(shí)體類(lèi)
*
* @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;
/**
* 活動(dòng)編碼
*/
private String activityCode;
/**
* 活動(dòng)名稱(chēng)
*/
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;
/**
* 活動(dòng)控制器
*
* @author zrj
* @since 2022-05-05 11:27:01
*/
@AutoAssemble
@RestController
@RequestMapping("/activity")
@Api(tags = "ActivityController", description = "活動(dòng)控制器")
public class ActivityController {
/**
* 服務(wù)對(duì)象
*/
@Resource
private ActivityService activityService;
/**
* 通過(guò)主鍵查詢單條數(shù)據(jù)
*
* @param activity 參數(shù)對(duì)象
* @return 單條數(shù)據(jù)
*/
@ApiOperation("通過(guò)主鍵查詢單條數(shù)據(jù)")
@GetMapping("/create")
public Response<Activity> get(Activity activity) {
System.out.println("用戶基礎(chǔ)信息:" + JSON.toJSONString(activity));
Activity result = activityService.selectById(activity.getId());
if (result != null) {
return Response.success("查詢成功", result);
}
return Response.fail("查詢失敗");
}
/**
* 新增一條數(shù)據(jù)
*
* @param activity 實(shí)體類(lèi)
* @return Response對(duì)象
*/
@ApiOperation("創(chuàng)建活動(dòng)")
@PostMapping("/create")
public Response<Activity> create(@RequestBody Activity activity) {
int result = activityService.insert(activity);
if (result > 0) {
return Response.success("新增成功", activity);
}
return Response.fail("新增失敗");
}
/**
* 修改一條數(shù)據(jù)
*
* @param activity 實(shí)體類(lèi)
* @return Response對(duì)象
*/
@ApiOperation("修改一條數(shù)據(jù)")
@PostMapping("/update")
public Response<Activity> update(@RequestBody Activity activity) {
Activity result = activityService.update(activity);
if (result != null) {
return Response.success("修改成功", result);
}
return Response.fail("修改失敗");
}
/**
* 通過(guò)實(shí)體作為篩選條件查詢
*
* @return Response對(duì)象
*/
@ApiOperation("通過(guò)實(shí)體作為篩選條件查詢")
@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("查詢失敗");
}
/**
* 分頁(yè)查詢
*
* @param start 偏移
* @param limit 條數(shù)
* @return Response對(duì)象
*/
@ApiOperation("分頁(yè)查詢")
@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. 測(cè)試驗(yàn)證


到此這篇關(guān)于Java切面統(tǒng)一處理Token設(shè)置用戶信息的文章就介紹到這了,更多相關(guān)Java處理Token設(shè)置用戶信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 實(shí)現(xiàn)文件復(fù)制和格式更改的實(shí)例
java 實(shí)現(xiàn)文件復(fù)制和格式更改的實(shí)例,需要的朋友可以參考一下2013-03-03
SpringBoot和Vue.js實(shí)現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng)
本文主要介紹了SpringBoot和Vue.js實(shí)現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
如何使用SpringBoot集成Kafka實(shí)現(xiàn)用戶數(shù)據(jù)變更后發(fā)送消息
Spring Boot集成Kafka實(shí)現(xiàn)用戶數(shù)據(jù)變更后,向其他廠商發(fā)送消息,我們需要考慮配置Kafka連接、創(chuàng)建Kafka Producer發(fā)送消息、監(jiān)聽(tīng)用戶數(shù)據(jù)變更事件,并將事件轉(zhuǎn)發(fā)到Kafka,本文分步驟給大家講解使用SpringBoot集成Kafka實(shí)現(xiàn)用戶數(shù)據(jù)變更后發(fā)送消息,感興趣的朋友一起看看吧2024-07-07
springboot?log4j2日志框架整合與使用過(guò)程解析
這篇文章主要介紹了springboot?log4j2日志框架整合與使用,包括引入maven依賴和添加配置文件log4j2-spring.xml的相關(guān)知識(shí),需要的朋友可以參考下2022-05-05
計(jì)算機(jī)二級(jí)考試java軟件操作教程 教大家如何學(xué)習(xí)java
如何成為一名知識(shí)豐富的Java程序員,順利通過(guò)計(jì)算機(jī)二級(jí)Java考試,這篇文章主要主要教大家如何學(xué)習(xí)java,java的學(xué)習(xí)路線是什么,從何學(xué)起,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Java利用apache ftp工具實(shí)現(xiàn)文件上傳下載和刪除功能
這篇文章主要為大家詳細(xì)介紹了Java利用apache ftp工具實(shí)現(xiàn)文件上傳下載、刪除功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
SSM項(xiàng)目使用攔截器實(shí)現(xiàn)登錄驗(yàn)證功能
這篇文章主要介紹了在SSM項(xiàng)目中如何使用攔截器,實(shí)現(xiàn)登錄驗(yàn)證功能。文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的小伙伴可以了解一下2022-01-01

