Nginx鉴权、限流问题

一、Nginx鉴权

1. 依赖模块 依赖模块

  • 依赖模块
1
http_auth_request_module
  • 验证是否安装
1
nginx -V 2>&1 | grep -- 'http_auth_request_module'

2. Nginx配置

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
server
{
    listen 80;
 
    location = /checkToken {
        internal;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header via $request_uri;
        proxy_pass $auth_request_url;
    }
 
    location = /auth401 {
        add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
        if ( $arg_via = "001" ) {
            return 401 "{"msg":"登录凭证为空","opCode":"001","operateSuccess":false}";
        }
        if ( $arg_via = "002" ) {
            return 401 "{"msg":"登录凭证失效","opCode":"002","operateSuccess":false}";
        }
        if ( $arg_via = "003" ) {
            return 401 "{"msg":"账户无权限","opCode":"003","operateSuccess":false}";
        }
    }
 
    location /test/api/ {
        set $auth_request_url "http://127.0.0.1:8080/test/api/token/check?token=$arg_token";
        auth_request /checkToken;
        auth_request_set $auth_via $upstream_http_via;
        error_page 401 = /auth401?via=$auth_via;
         
        proxy_pass http://127.0.0.1:8080/test/api/;
    }
 
}

3. Rest接口

  • 验证的Redis账户权限内容
  • TokenRest.java
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
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Set;
 
@RestController
@RequestMapping("/api/token")
public class TokenRest {
 
    @Resource
    private RedisTemplate redisTemplate;
 
    @GetMapping(value="check")
    public void checkRest(HttpServletRequest request, HttpServletResponse response) {
        response.setStatus(401);
        try {
            String url = request.getHeader("via");
            if (StringUtils.isNotEmpty(url) && url.contains("?")) {
                url = url.substring(0, url.indexOf("?"));
            }
            // 白名单跳过验证
            String flag = (String) redisTemplate.opsForHash().get("whiteCache", url);
            if (StringUtils.isNotEmpty(flag)) {
                response.setStatus(200);
                return;
            }
            // 从Head或url中获取token
            String token = request.getParameter("token");
            if (StringUtils.isEmpty(token) || "null".equals(token)) {
                token = request.getHeader("Authorization");
                if (token!=null && token.startsWith("Bearer ")) {
                    token = token.substring(7);
                }
            }
            if (StringUtils.isEmpty(token) || "null".equals(token)) {
                response.setHeader("via", "001");
                return;
            }
            // 从Redis中获取账户信息
            String accountId = (String) redisTemplate.opsForValue().get(token);
            if (accountId == null) {
                response.setHeader("via", "002");
                return;
            }
            Map info = (Map) redisTemplate.opsForValue().get(accountId);
            if (info == null) {
                response.setHeader("via", "003");
                return;
            }
            String[] roleIds = info.get("roles").split(",");
            for (String roleId : roleIds) {
                Set securityUrls = (Set) redisTemplate.opsForHash().get("funcCache",roleId);
                if (securityUrls.contains(url)) {
                    flag = "1";
                    break;
                }
            }
            if ("1".equals(flag)) {
                response.setStatus(200);
            } else {
                response.setHeader("via", "003");
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}
  • 验证的Redis账户权限内容

二、Nginx限流

1. 简介

Nginx限流是一种用于保护系统资源、防止恶意攻击和控制流量的技术。

  • 控制速率:使用 ngx_http_limit_req_module 模块,可以限制每个IP地址单位时间内的请求数。
  • 控制连接数:使用 ngx_http_limit_conn_module 模块,可以限制每个IP地址同时保持的连接数。

2. 控制速率

  • nginx.conf
1
2
3
4
http
{
    limit_req_zone $binary_remote_addr zone=limit_req:10m rate=2r/s;
}
说明
binary_remote_addr 表示通过客户端IP来限制
zone 共享内存区存储访问信息
limit_req:10m 名字为limit_req的内存区域,存储16万IP地址
rate=2r/s 表示每秒最多处理2个请求
1
2
3
4
5
6
7
server
{
    location = /test.htm {
        limit_req zone=limit_req burst=10 nodelay;
        alias C:/nginx/html/test.htm;
    }
}
说明
burst=10 突发请求不超过10个
nodelay 不延迟处理超过限制的请求

3. 控制连接数

  • nginx.conf
1
2
3
4
http
{
    limit_conn_zone $binary_remote_addr zone=limit_conn:10m;
}
说明
binary_remote_addr 表示通过客户端IP来限制
zone 共享内存区存储访问信息
limit_conn:10m 名字为limit_conn的内存区域,存储16万IP地址
1
2
3
4
5
6
7
server
{
    location = /test.htm {
        limit_conn limit_conn 2;
        alias C:/nginx/html/test.htm;
    }
}
说明
limit_conn 2 同一个IP地址只允许保持2个连接

总结

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

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/server/nginx/12702.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部