Springboot 如何实现filter拦截token验证和跨域

Springboot filter拦截token验证和跨域

背景

web验证授权合法的一般分为下面几种

  • 使用session作为验证合法用户访问的验证方式
  • 使用自己实现的token
  • 使用OCA标准

在使用API接口授权验证时,token是自定义的方式实现起来不需要引入其他东西,关键是简单实用。

合法登陆后一般使用用户UID+盐值+时间戳使用多层对称加密生成token并放入分布式缓存中设置固定的过期时间长(和session的方式有些相同),这样当用户访问时使用token可以解密获取它的UID并据此验证其是否是合法的用户。

#springboot中实现filter

  • 一种是注解filter
  • 一种是显示的硬编码注册filter

先有filter

import javax.servlet.annotation.WebFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import springfox.documentation.spring.web.json.Json;
import com.alibaba.fastjson.JSON;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/***************
 * token验证拦截
 * @author bamboo zjcjava@163.com
 * @time 2017-08-01
 */
@Component
//@WebFilter(urlPatterns = { "/api/v/*" }, filterName = "tokenAuthorFilter")
public class TokenAuthorFilter implements Filter {
 private static Logger logger = LoggerFactory
   .getLogger(TokenAuthorFilter.class);
 @Override
 public void destroy() {
 }
 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  HttpServletRequest req = (HttpServletRequest) request;
  HttpServletResponse rep = (HttpServletResponse) response;
  //设置允许跨域的配置
  // 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
  rep.setHeader("Access-Control-Allow-Origin", "*");
  // 允许的访问方法
  rep.setHeader("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE, PATCH");
  // Access-Control-Max-Age 用于 CORS 相关配置的缓存
  rep.setHeader("Access-Control-Max-Age", "3600");
  rep.setHeader("Access-Control-Allow-Headers","token,Origin, X-Requested-With, Content-Type, Accept");
  response.setCharacterEncoding("UTF-8");
  response.setContentType("application/json; charset=utf-8");
  String token = req.getHeader("token");//header方式
  ResultInfo resultInfo = new ResultInfo();
  boolean isFilter = false;  

  String method = ((HttpServletRequest) request).getMethod();
  if (method.equals("OPTIONS")) {
   rep.setStatus(HttpServletResponse.SC_OK);
  }else{

   if (null == token || token.isEmpty()) {
    resultInfo.setCode(Constant.UN_AUTHORIZED);
    resultInfo.setMsg("用户授权认证没有通过!客户端请求参数中无token信息");
   } else {
    if (TokenUtil.volidateToken(token)) {
     resultInfo.setCode(Constant.SUCCESS);
     resultInfo.setMsg("用户授权认证通过!");
     isFilter = true;
    } else {
     resultInfo.setCode(Constant.UN_AUTHORIZED);
     resultInfo.setMsg("用户授权认证没有通过!客户端请求参数token信息无效");
    }
   }
   if (resultInfo.getCode() == Constant.UN_AUTHORIZED) {// 验证失败
    PrintWriter writer = null;
    OutputStreamWriter osw = null;
    try {
     osw = new OutputStreamWriter(response.getOutputStream(),
       "UTF-8");
     writer = new PrintWriter(osw, true);
     String jsonStr = JSON.toJSONString(resultInfo);
     writer.write(jsonStr);
     writer.flush();
     writer.close();
     osw.close();
    } catch (UnsupportedEncodingException e) {
     logger.error("过滤器返回信息失败:" + e.getMessage(), e);
    } catch (IOException e) {
     logger.error("过滤器返回信息失败:" + e.getMessage(), e);
    } finally {
     if (null != writer) {
      writer.close();
     }
     if (null != osw) {
      osw.close();
     }
    }
    return;
   }

   if (isFilter) {
   logger.info("token filter过滤ok!");
   chain.doFilter(request, response);
   }
  }
 }
 @Override
 public void init(FilterConfig arg0) throws ServletException {
 }
}

注解配置filter

加上如下配置则启动时会根据注解加载此filter

@WebFilter(urlPatterns = { “/api/*” }, filterName = “tokenAuthorFilter”)

硬编码注册filter

在application.java中加入如下代码

    //注册filter
    @Bean
    public FilterRegistrationBean  filterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        TokenAuthorFilter tokenAuthorFilter = new TokenAuthorFilter();
        registrationBean.setFilter(tokenAuthorFilter);
        List<String> urlPatterns = new ArrayList<String>();
        urlPatterns.add("/api/*");
        registrationBean.setUrlPatterns(urlPatterns);
        return registrationBean;
    }  

以上两种方式都可以实现filter

跨域说明

springboot可以设置全局跨域,但是对于filter中的拦截地址并不其中作用,因此需要在dofilter中再次设置一次

区局设置跨域方式如下

方式1.在application.java中加入如下代码

 //跨域设置
 private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }  

    /**
     * 跨域过滤器
     * @return
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }  

方式2.配置注解

必须集成WebMvcConfigurerAdapter类

/**********
 * 跨域 CORS:使用 方法3
 * 方法:
 1服务端设置Respone Header头中Access-Control-Allow-Origin
 2配合前台使用jsonp
 3继承WebMvcConfigurerAdapter 添加配置类
 http://blog.csdn.net/hanghangde/article/details/53946366
 * @author xialeme
 *
 */
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter{  

   /* @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                .maxAge(3600);
    }  */

 private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1
        corsConfiguration.addAllowedHeader("*"); // 2
        corsConfiguration.addAllowedMethod("*"); // 3
        return corsConfiguration;
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }
}

springboot配置Filter & 允许跨域请求

1.filter类

加注解:

@WebFilter(filterName = "authFilter", urlPatterns = "/*")

代码如下:

package com.activiti.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

// renwenqiang
@WebFilter(filterName = "authFilter", urlPatterns = "/*")
public class SystemFilter implements Filter {

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
            ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin","*");
        System.out.println(request.getRequestURL());
        filterChain.doFilter(request, servletResponse);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}

2.启动类

加注解:

@ServletComponentScan(basePackages = {"com.activiti.filter"})

代码如下:

package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication(exclude = {
        org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
        org.activiti.spring.boot.SecurityAutoConfiguration.class })
@ServletComponentScan(basePackages = {"com.activiti.filter"})
public class DemoActiviti0108Application {

    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory() {
        return new HibernateJpaSessionFactoryBean();
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoActiviti0108Application.class, args);
    }
}

3.jquery ajax请求代码实例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<div id="app">
<hr>
<h2>模型列表</h2>
<a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="huizhi">绘制流程</a>
<hr>
<table border="1">
    <tr>
        <td>id</td>
        <td>deploymentId</td>
        <td>name</td>
        <td>category</td>
        <td>optional</td>
    </tr>
    <tr v-for="item in models">
        <td>{{ item.id }}</td>
        <td>{{ item.deploymentId }}</td>
        <td>{{ item.name }}</td>
        <td>{{ item.category }}</td>
        <td>
            <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >编辑</a>&nbsp;&nbsp;
            <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >发布</a>&nbsp;&nbsp;
            <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >删除</a>
        </td>
    </tr>
</table>
</div>

    <script src="https://cdn.bootcss.com/jquery/2.2.2/jquery.js"></script>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
    <script>
    new Vue({
      el: '#app',
      data: {
        models: []
      },
      created: function () {
        $.ajax({
            type: 'GET',
            url: 'http://localhost:8081/activiti/model/all',
            beforeSend: function() {
                console.log('beforeSend');
            },
            data:{},
            dataType: "json",
            xhrFields: {
                withCredentials: false
            },
            crossDomain: true,
            async: true,
            //jsonpCallback: "jsonpCallback",//服务端用于接收callback调用的function名的参数
        }).done((data) => {
            console.log('done');
            console.log(data);
            this.models = data;
        }).fail((error) => {
            console.log('fail');
            console.log('error');
        });
      }
    })
    </script>
</body>
</html>

大功告成 回家睡觉 嘻嘻嘻~

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JAVA通过Filter实现允许服务跨域请求的方法

    概念 在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址, 而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样. 这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域即我们常说的浏览器请求的同源策略. Jsonp 在前后端分离的项目中,会经常遇到需要跨域请求的问题.跨域请求有

  • Springboot处理CORS跨域请求的三种方法

    前言 Springboot跨域问题,是当前主流web开发人员都绕不开的难题.但我们首先要明确以下几点 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了. 之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议.域名.端口号都完全一致. 浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的H

  • Spring Boot配置拦截器及实现跨域访问的方法

    拦截器功能强大,能够深入方法前后,常应用于日志记录.权限检查和性能检测等,几乎是项目中不可或缺的一部分,本文就来实现Spring Boot自定义拦截器的配置. 理论指导 问:Spring Boot怎么配置拦截器? 答:配置一个拦截器需要两步完成. 自定义拦截器,实现HandlerInterceptor这个接口.这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是

  • springboot配置允许跨域访问代码实例

    这篇文章主要介绍了springboot配置允许跨域访问代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 因springboot框架通常用于前后端分离项目,因此需配置后台允许跨域访问(具体看注释),配置类如下,将该类加入工程中即可. import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configu

  • 详解springboot设置cors跨域请求的两种方式

    1.第一种: public class CorsFilter extends OncePerRequestFilter { static final String ORIGIN = "Origin"; protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOE

  • Springboot 如何实现filter拦截token验证和跨域

    Springboot filter拦截token验证和跨域 背景 web验证授权合法的一般分为下面几种 使用session作为验证合法用户访问的验证方式 使用自己实现的token 使用OCA标准 在使用API接口授权验证时,token是自定义的方式实现起来不需要引入其他东西,关键是简单实用. 合法登陆后一般使用用户UID+盐值+时间戳使用多层对称加密生成token并放入分布式缓存中设置固定的过期时间长(和session的方式有些相同),这样当用户访问时使用token可以解密获取它的UID并据此验

  • asp.net基于JWT的web api身份验证及跨域调用实践

    随着多终端的出现,越来越多的站点通过web api restful的形式对外提供服务,很多网站也采用了前后端分离模式进行开发,因而在身份验证的方式上可能与传统的基于cookie的Session Id的做法有所不同,除了面临跨域提交cookie的烦人问题外,更重要的是,有些终端可能根本不支持cookie. Json Web Token(jwt)是一种不错的身份验证及授权方案,简单的说就是调用端调用api时,附带上一个由api端颁发的token,以此来验证调用者的授权信息. 但由于时间关系,不对jw

  • Springboot升级至2.4.0中出现的跨域问题分析及修改方案

    问题 Springboot升级至2.4.0中出现的跨域问题. 在Springboot 2.4.0版本之前使用的是2.3.5.RELEASE,对应的Spring版本为5.2.10.RELEASE. 升级至2.4.0后,对应的Spring版本为5.3.1. Springboot2.3.5.RELEASE时,我们可以使用CorsFilter设置跨域. 分析 版本2.3.5.RELEASE 设置跨域 设置代码如下: @Configuration public class ResourcesConfig

  • SpringBoot+Vue前后端分离实现请求api跨域问题

    前言 最近过年在家无聊,刚好有大把时间学习Vue,顺便做了一个增删查改+关键字匹配+分页的小dome,可是使用Vue请求后端提供的Api的时候确发现一个大问题,前后端分离了,但是请求的时候也就必定会有跨域这种问题,那如何解决呢? 前端解决方案 思路:由于Vue现在大多数项目但是用脚手架快速搭建的,所以我们可以直接在项目中创建一个vue.config.js的配置文件,然后在里面配置proxy代理来解决,话不多说,直接上代码 module.exports = { devServer: { proxy

  • 使用Filter拦截器如何实现请求跨域转发

    目录 Filter拦截器实现请求跨域转发 在使用Filter实现转发后特做一次记录 使用filter解决跨域 在web.xml配置拦截器 过滤器代码 Filter拦截器实现请求跨域转发 因为公司项目需求,项目中前端请求需要通过一个类似中转的服务转发(请求在该服务中会重新包装一些通用参数) 在使用Filter实现转发后特做一次记录 package com.unicloud.cce.Filter; import com.alibaba.fastjson.JSON; import com.uniclo

  • springboot跨域如何设置SameSite的实现

    前言 今天记录一个前段时间遇到的一个小问题的解决方法, 跨域!!! 相信跨域这个问题, 做开发的或多或少都遇到过, 而且已经有很多博主已经分享了相关的内容, 这次我用他们的方式都没有解决到, 所以记录一下. 问题 我们公司有个系统的域名跟主系统的域名不一致, 但是我们又需要把所有的系统都集成在一个框架下面, 使用的是iframe技术来实现. 使用单点登录来做所有系统的登录. 这样的设计就导致我们访问域名不同的系统的时候, 会有跨域的问题. 通常的解决方式这样, 在springboot里面设置跨域

  • 使用ajax跨域调用springboot框架的api传输文件

    在新项目中使用的是springboot编写的api,涉及到ajax跨域请求和传输文件的问题,在这里记录一下 首先是前台页面的代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test_api</title> <script type="text/javascript" src="jquery-1.7.2.

  • SpringBoot集成JWT实现token验证的流程

    JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息.因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名. JWT请求流程 1. 用户使

  • SpringBoot整合JWT框架,解决Token跨域验证问题

    一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3.服务器向返回sessionId,写入客户端 Cookie. 4.客户端每次请求,需要通过 Cookie,将 sessionId 回传服务器. 5.服务器收到 sessionId,验证客户端. 2.存在问题 1.session保存在服务端,客户端访问高并发时,服务端压力大. 2.扩展性差,服务器集群,就需要 session 数据共享. 二.JWT简介 JWT

随机推荐