好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

Springboot filter拦截token验证和跨域

背景

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

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

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

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

#springboot中实现filter

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

先有filter

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

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测试数据

  * @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

?

1

@WebFilter (urlPatterns = { [/api/*] }, filterName = [tokenAuthorFilter])

硬编码注册filter

在application.java中加入如下代码

?

1

2

3

4

5

6

7

8

9

10

11

//注册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中加入如下代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//跨域设置

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类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

/**********

  * 跨域 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类

加注解:

?

1

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

代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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.启动类

加注解:

?

1

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

代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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请求代码实例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

<!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测试数据/jquery/2.2.2/jquery.js" ></script>

     <script src= "https://cdn.bootcss测试数据/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>

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

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

原文链接:https://blog.csdn.net/zjcjava/article/details/78237164

查看更多关于Springboot 如何实现filter拦截token验证和跨域的详细内容...

  阅读:29次