java 注解声明服务_Java自定义注解(三)

前面介绍了如何获取注解的值,那么本篇将介绍如何真正的在实际的业务中去使用()自定义注解,并且结合JWT组件来实现用户信息的通过注解的方式来获取

JWT工具类

package com.example.util;

import com.auth0.jwt.JWT;

import com.auth0.jwt.JWTVerifier;

import com.auth0.jwt.algorithms.Algorithm;

import com.auth0.jwt.interfaces.Claim;

import com.auth0.jwt.interfaces.DecodedJWT;

import org.springframework.util.DigestUtils;

import java.util.Date;

import java.util.HashMap;

public class JwtUtils {

//需要的过期时间

public final static long EXPIRE_TIME = 60 * 1000;

//需要的生成密钥,防止token伪造

public final static String TOKEN_SECRET = "5d41402abc4b2a76b9719d911017c592";

/**

* 根据用户id生成token

*

* @param id 用户id

* @return

*/

public static String generateToken(String id) {

Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);

//使用hash算法

Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);

HashMap header = new HashMap<>();

header.put("type", "JWT");

header.put("alg", "HMAC256");

String token = JWT.create().withHeader(header).withExpiresAt(date).withClaim("id", id).sign(algorithm);

return token;

}

/**

* 验证token是否是服务器颁发的

*

* @param token 用户传过来的token参数

* @return

*/

public static boolean verifyToken(String token) {

try {

Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);

JWTVerifier build = JWT.require(algorithm).build();

build.verify(token);

return true;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

/**

* 从token中取出负载,即JWT create的时候加入的claim

*

* @param token

* @return

*/

public static String getClaim(String token) {

DecodedJWT decode = JWT.decode(token);

Claim id = decode.getClaim("id");

return id.asString();

}

public static void main(String[] args) {

//生成一个token

System.out.println(generateTokenSecret());

//根据用户id生成一个token

String token = generateToken("10");

//校验token

verifyToken(token);

//获取token中的负载,也就是当时传入进去的值

System.out.println(getClaim(token));

}

/**

* 用md5生成一个密钥

*

* @return

*/

public static String generateTokenSecret() {

return DigestUtils.md5DigestAsHex("hello".getBytes());

}

}

自定义注解

package com.example.annotaion;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

public @interface UserId {

}

使用HandlerMethodArgumentResolver

在resolver里面来处理校验token逻辑,同时根据用户传参数信息,通过自己到校验逻辑,封装用户信息到自定义注解里面的参数里

package com.example.resolver;

import com.example.annotaion.UserId;

import com.example.util.JwtUtils;

import org.springframework.core.MethodParameter;

import org.springframework.web.bind.support.WebDataBinderFactory;

import org.springframework.web.context.request.NativeWebRequest;

import org.springframework.web.method.support.HandlerMethodArgumentResolver;

import org.springframework.web.method.support.ModelAndViewContainer;

public class UserIdHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

@Override

public boolean supportsParameter(MethodParameter parameter) {

return parameter.getParameterType().isAssignableFrom(String.class)

&& parameter.hasParameterAnnotation(UserId.class);

}

@Override

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

String token = webRequest.getParameter("token");

boolean b = JwtUtils.verifyToken(token);

if (b) {

return JwtUtils.getClaim(token);

}

return null;

}

}

注册参数解析器

import com.example.interceptor.AuthenticationInterceptor;

import com.example.resolver.UserIdHandlerMethodArgumentResolver;

import com.example.resolver.UserInfoArgumentResolver;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.method.support.HandlerMethodArgumentResolver;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

//配置拦截器

@Configuration

public class WebMvcConfig implements WebMvcConfigurer {

@Override

public void addArgumentResolvers(List resolvers) {

// resolvers.add(new UserInfoArgumentResolver());

resolvers.add(new UserIdHandlerMethodArgumentResolver());

}

}

controller里面的使用

package com.example.controller;

import com.example.annotaion.CacheResult;

import com.example.annotaion.KeyVerify;

import com.example.annotaion.LoginUserInfo;

import com.example.annotaion.UserId;

import com.example.entity.LoginUser;

import com.example.util.JwtUtils;

import lombok.extern.slf4j.Slf4j;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

import java.util.Map;

@RestController

@CacheResult(key = "class_key", cacheName = "class_cacheName")

@Slf4j

public class TestController {

/**

* 模拟用户登录,登录成功后返回给用户一个token

* @param userid

* @return

*/

@RequestMapping("/login")

public Map select(@UserId String userid) {

HashMap map = new HashMap<>();

log.info("用户认证通过,id是:{}", userid);

map.put("code", 200);

String oid = "10";

map.put("token", JwtUtils.generateToken(oid));

return map;

}

/**

* 用户拿着token来付款,此时参数中没有用户的id信息,但是可以通过解析器里面的token来获取

* @param id

* @param token

*/

@RequestMapping("pay")

public String pay(@UserId String id, String token) {

log.info("id:{}", id);

return id;

}

}

login方法模拟用户登录,用户登录成功之后,返回一个token给用户,当用户下次访问付款接口当时候,传统的从session中获取用户信息的伪代码如下

@RequestMapping("/pay2")

public void pay(HttpServletRequest request) {

HttpSession session = request.getSession();

User user = (User)session.getAttribute("user-info");

String token = request.getParameter("token");

boolean b = JwtUtils.verifyToken(token);

if (b){

String id = JwtUtils.getClaim(token);

log.info("id:{}", id);

}

}

但是通过使用解析器以及自定义注解,我们成功得将校验逻辑和业务分离了,整个controller里面变得清洁了

请求测试

登录服务器

付款请求

控制台输出

2021-03-04 16:20:51.216 INFO 15612 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'

2021-03-04 16:20:51.216 INFO 15612 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'

2021-03-04 16:20:51.220 INFO 15612 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms

2021-03-04 16:20:51.243 INFO 15612 --- [nio-8080-exec-1] com.example.controller.TestController : 用户认证通过,id是:null

2021-03-04 16:21:05.735 INFO 15612 --- [nio-8080-exec-2] com.example.controller.TestController : id:10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值