不灭的火

革命尚未成功,同志仍须努力下载JDK17

作者:AlbertWen  添加时间:2021-06-02 14:12:37  修改时间:2025-04-27 21:18:27  分类:07.Java框架/系统  编辑

本文给每个rest接口上添加过滤器,使用过滤器实现简单的Http Basic认证

1、Filter功能

Filter,它使用户可以改变一个request和修改一个response。Filter 不是一个servlet,它不能产生一个response,但它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response。换种说法,filter其实是一个”servlet chaining”(servlet 链)。

一个Filter包括:

1)在servlet被调用之前截获;
2)在servlet被调用之前检查servlet request;
3)根据需要修改request头和request数据;
4)根据需要修改response头和response数据;
5)在servlet被调用之后截获。

2、定义自己的过滤器

新增HTTPBasicAuthorizeAttribute.java

如果请求的Header中存在Authorization: Basic头信息,且用户名密码正确,则继续原来的请求,否则返回没有权限的错误信息

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
package com.wenjianbao.sunt.filter;
  
import java.io.IOException;
  
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;
  
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wenjianbao.sunt.utils.ResultMsg;
import com.wenjianbao.sunt.utils.ResultStatusCode;
import sun.misc.BASE64Decoder;
  
@SuppressWarnings("restriction")
public class HTTPBasicAuthorizeAttribute implements Filter{
     
    private static String Name = "test";
    private static String Password = "test";
  
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
         
    }
  
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
         
        ResultStatusCode resultStatusCode = checkHTTPBasicAuthorize(request);
        if (resultStatusCode != ResultStatusCode.OK) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setCharacterEncoding("UTF-8"); 
            httpResponse.setContentType("application/json; charset=utf-8");
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  
            ObjectMapper mapper = new ObjectMapper();
             
            ResultMsg resultMsg = new ResultMsg(ResultStatusCode.PERMISSION_DENIED.getErrcode(), ResultStatusCode.PERMISSION_DENIED.getErrmsg(), null);
            httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));
            return;
        } else {
            chain.doFilter(request, response);
        }
    }
  
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
         
    }
     
    private ResultStatusCode checkHTTPBasicAuthorize(ServletRequest request) {
        try {
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            String auth = httpRequest.getHeader("Authorization");
             
            if ((auth != null) && (auth.length() > 6)) {
                String HeadStr = auth.substring(0, 5).toLowerCase();
                if (HeadStr.compareTo("basic") == 0) {
                    auth = auth.substring(6, auth.length()); 
                    String decodedAuth = getFromBASE64(auth);
                    if (decodedAuth != null) {
                        String[] UserArray = decodedAuth.split(":");
                         
                        if (UserArray != null && UserArray.length == 2) {
                            if (UserArray[0].compareTo(Name) == 0 && UserArray[1].compareTo(Password) == 0) {
                                return ResultStatusCode.OK;
                            }
                        }
                    }
                }
            }
            return ResultStatusCode.PERMISSION_DENIED;
        } catch(Exception ex) {
            return ResultStatusCode.PERMISSION_DENIED;
        }
         
    }
     
    private String getFromBASE64(String s) { 
        if (s == null) {
            return null;
        
         
        BASE64Decoder decoder = new BASE64Decoder(); 
        try
            byte[] b = decoder.decodeBuffer(s); 
            return new String(b); 
        } catch (Exception e) { 
            return null
        
    }
  
}

3、在SpringRestApplication类中注册过滤器,给user/*都加上http basic认证过滤器

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
package com.xiaofangtech.sunt;
  
import java.util.ArrayList;
import java.util.List;
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
  
import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute;
  
@SpringBootApplication
public class SpringRestApplication {
  
    public static void main(String[] args) {
        SpringApplication.run(SpringRestApplication.class, args);
    }
     
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute();
        registrationBean.setFilter(httpBasicFilter);
        List<String> urlPatterns = new ArrayList<String>();
        urlPatterns.add("/user/*");
        registrationBean.setUrlPatterns(urlPatterns);
         
        return registrationBean;
    }
}

4、测试

代码中固定用户名密码都为test,所以对接口进行请求时,需要添加以下认证头信息

1
Authorization: Basic dGVzdDp0ZXN0

dGVzdDp0ZXN0 为 test:test 经过base64编码后的结果

如果未添加认证信息或者认证信息错误,返回没有权限的错误信息

当认证信息正确,返回请求结果