利用JWT、注解拦截请求并验证token

在Web应用程序中,注解是一种方便的方式来拦截和处理请求。可以通过在代码中添加注解来定义一些特殊的行为,比如拦截器(Interceptor)等。
拦截器是一种处理请求的技术,它可以在请求被处理之前或之后对请求进行处理。通过使用拦截器,可以在处理请求之前或之后添加额外的逻辑,例如身份验证、权限检查等。

所需JWT依赖:
	<dependency>
	    <groupId>com.auth0</groupId>
	    <artifactId>java-jwt</artifactId>
	    <version>4.2.1</version>
	</dependency>
定义一个登录用户类:
/**
 * @Author RainCity
 * @Date 2021-05-24 10:49:59
 * @Desc 登录用户
 */
public class LoginUser implements Serializable {
    private static final long serialVersionUID = 768788313972112861L;

    /**登录名*/
    private String loginName;
    /**登录密码*/
    private String password;

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "LoginUser {" +
                "loginName='" + loginName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
利用JWT生成token:
/**
 * @Author RainCity
 * @Date 2021-05-24 11:47:04
 * @Desc jwt 根据当前登录人生成token
 */
public class JsonWebToken {
    private static final String ISSUER="ISSUER";

    /**
     * 生成token---有过期时间
     * @param loginName 登录名(唯一标识)
     * @param password 登陆密码
     * @param second 多少秒后过期
     * @return {@link String}
     * @version v1.0.0
     */
    public static String createToken(String loginName, String password, int second) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.SECOND, second);
        return JWT.create()
                .withJWTId("jwt_id")
                //签发者
                .withIssuer(ISSUER)
                //将 登录名 保存到token里面
                .withAudience(loginName)
                //签发时间
                .withIssuedAt(new Date())
                //过期时间
                .withExpiresAt(cal.getTime())
                //以 password 作为token的密钥
                .sign(Algorithm.HMAC256(password));
    }
	
	/**
     * 生成token---无过期时间
     * @param loginName 登录名(唯一标识)
     * @param password 登陆密码
     * @return {@link String}
     * @version v1.0.0
     */
    public static String createToken(String loginName, String password) {
        return JWT.create()
                .withJWTId("jwt_id")
                //签发者
                .withIssuer(ISSUER)
                //将 登录名 保存到token里面
                .withAudience(loginName)
                //签发时间
                .withIssuedAt(new Date())
                //过期时间
                //.withExpiresAt(cal.getTime())
                //以 loginName+password 作为token的密钥
                .sign(Algorithm.HMAC256(loginName+password));
    }
}
注解:
/**
 * @Author RainCity
 * @Date 2021-05-24 10:25:39
 * @Desc 在需要验证的方法上使用此注解
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthRequired {
    boolean required() default true;
}
请求拦截器:
/**
 * @Author RainCity
 * @Date 2021-05-24 10:39:24
 * @Desc
 */
@SuppressWarnings(value = {"rawtypes" })
public class AuthenticationInterceptor implements AsyncHandlerInterceptor {

    @Resource
    public RedisTemplate redisTemplate;

    private static final String INVALID_MSG ="登录失效,请重新登录";
    private static final String NOT_EXIST_MSG ="用户不存在,请重新登录";

	private static final String LOGIN_KEY = "CUS_LOGIN:";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判断接口是否需要登录
        AuthRequired methodAnnotation = method.getAnnotation(AuthRequired.class);
        // 有 @AuthRequired 注解,需要认证
        if(null != methodAnnotation){
            // 执行认证
            // 从 http 请求头中取出 token
            String token = request.getHeader("token");
            Assert.notNull(token, "未登录");
            String loginName;
            try {
                // 获取 token 中的 账号
                loginName = JWT.decode(token).getAudience().get(0);
                if(StringUtils.isEmpty(loginName)){
                    throw new RuntimeException(INVALID_MSG);
                }
                LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(LOGIN_KEY + loginName);
                if (null == loginUser) {
                    throw new RuntimeException(NOT_EXIST_MSG);
                }
                // 验证 token
                JWTVerifier verifier = JWT.require(Algorithm.HMAC256(loginUser.getLoginName()+loginUser.getPassword())).build();
                verifier.verify(token);
                return true;
            } catch (JWTVerificationException e) {
                throw new RuntimeException("身份认证失败");
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) {

    }
}

注解拦截请求是一种优雅而灵活的方式,可以帮助我们更好地管理和处理请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java EE常用框架 WebService 介绍 基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求。从而实现远程调用 术语 XML. Extensible Markup Language -扩展性标记语言 WSDL – WebService Description Language – Web服务描述语言。 SOAP-Simple Object Access Protocol(简单对象访问协议) SOA(Service-Oriented Architecture) :面向服务的架构 它是一种思想,IBM大力倡导是即插即用的,IBM大力提倡,希望以组装电脑的方式来开发应用 它是目录服务,通过该服务可以注册和发布webservcie,以便第三方的调用者统一调用 使用: 二、我们可以使用Java自带的WsImport来实现本地代理。这种方法会将WebService翻译成Java类,我们使用类一样去访问WebService就行了。非常好用。 三、除了调用别人发布的webService,也可以自己发布WebService服务 四、CXF框架可以与spring无缝连接,就不用我们自己Endpoint了。它还能记录日志之类的 五、我们还可以使用Idea下的webservice,能够使用图形画面的方式获取本地代理和生成WSDL文件。 Activiti 介绍 Activiti5是一个业务流程管理(BPM)框架 如果我们的业务是比较复杂的话,我们才会用到工作流! 使用Activiti的步骤 定义工作流 画一个BPMN图就可以了 部署工作流 执行工作流-->按照我们定义的工作流来执行 工作流在执行的过程中肯定会涉及到很多数据,Activiti是默认提供数据库表给我们使用的 Activiti工作流框架快速入门: 定义工作流,使用插件来把我们的流程图画出来。这个流程图就是我们定义的工作流。 工作流引擎是工作流的核心,能够让我们定义出来的工作流部署起来。 由于我们使用工作流的时候是有很多数据产生的,因此Activiti是将数据保存到数据库表中的。这些数据库表由Actitviti创建,由Activiti维护。 部署完的工作流是需要手动去执行该工作流的。 根据由谁处理当前任务,我们就可以查询出具体的任务信息。 根据任务的id,我们就可以执行任务了。 细节 流程定义:涉及到了四张数据库表 我们可以通过API把我们的流程定义图读取出来 可以根据查询最新版本的流程定义 删除流程定义 部署流程定义的时候也可以是ZIP文件 流程运行:涉及到两个对象,四张数据库表: 流程实例 获取流程实例和任务的历史信息 判断流程实例是否为空来判断流程是否结束了 查看正在运行服务的详细信息 通过流程实例来开启流程 流程变量:它涉及到了两张表。 流 程变量实际上就是我们的条件。 作用 我们可以在流程开始的时候设置流程变量,在任务完成的时候设置流程变量。 运行时服务和流程任务都可以设置流程变量。 连线 通过连线我们可以在其中设置条件,根据不同的条件流程走不同的分支 排他网关 SpringData JPA 简介 API Repository接口 PagingAndSortingRepository JpaRepository JpaSpecificationExecutor 过滤条件查询接口 注解 nameQuery注解 SQL命名,调用的时候根据名称调用 查询注解 1,targetEntity 属性表示默认关联的实体类型,默认为当前标注的实体类。 2,cascade属性表示与此实体一对一关联的实体的级联样式类型。 3,fetch属性是该实体的加载方式,默认为即时加载EAGER 4,optional属性表示关联的该实体是否能够存在null值,默认为ture,如果设置为false,则该实体不能为null, 5, mapperBy属性:指关系被维护端 1,@JoinColumn注释是保存表与表之间关系的字段 2,如果不设置name,默认name = 关联表的名称+”-“+关联表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值