1.Nginx的前置准备

要通过Nginx搭配spring security进行鉴权,Nginx需要使用下面这个模块 --with-http_auth_request_module window环境版本的nginx默认是开启的,直接可以使用,linux系统的需要手动开启

  1. linux使用 --with-http_auth_request_module模块
    先查看当前系统下的nginx版本,只有安装的有模块了才会看到除了版本之外的信息。
[root ~]# nginx -V
nginx version: nginx/1.21.3
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-4) (GCC) 
built with OpenSSL 1.1.1k  FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_auth_request_module

上面命令即可查看nginx的版本,以及开启了那些模块,如果执行上述命令 ‘提示未找到命令’
则需要配置path
即:

[root ~]# vim /etc/profile

#对profiel文件最下面 添加下面代码 
#此处是你nginx安装路径,根据自己实际情况修改
PATH=$PATH:/usr/local/nginx/sbin

然后即可使用 nginx -V 查看信息了

  1. 如果安装过 --with-http_auth_request_module模块 则忽略此处,如果没有则按下述操作
    进入nginx解压目录下,查看是否有 congiure这个文件,如果没有则需要去官方网址:http://nginx.org/en/download.html下载对应的版本,进行解压,并把解压下的congiure文件,复制到nginx目录下,
    执行下面命令:
    说明:nginx的解压地址和安装地址可能不同,解压地址下包含configure不包含sbin, nginx的安装地址下没有configure,有sbin。
#说明 profix= 自己nginx安装地址 后面--with-xx的根据通过命令 nginx -V 查询到的都需要添加上,此处只多添加一个--with-http_auth_request_module 这个模块,有需要其他模块的 自行查找添加。
[root nginx]# ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_auth_request_module
#然后执行
[root nginx]# make
[root nginx]# make install
#在执行nginx -V即可查看到 安装的模块
[root nginx]# nginx -V
  1. Nginx的配置
#此处拦截 根据自己需求进行拦截
          location  /static/profile {
                    auth_request /check;
                    error_page 401 = /auth_page;
                    proxy_pass http://localhost:8080/profile;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        #认证路径
        location = /check {
                    #表示该路径仅仅为nginx内部访问,一旦出了这个配置文件,则失效
                    internal;
                    #自己系统的认证路径
                    proxy_pass http://localhost:8080/check;
                    error_page 401 402 403 404  /auth_page;
        }
        #认证失败后的处理
        location = /auth_page{
                    #强制浏览器不使用缓存,防止缓存带来的还能访问系统
                    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
                    #如果认证失败,跳转到自己系统的登录页面
                    return  https://xxx/login;
        }
  1. 后台代码编写请求接口,需与上面Nginx配置的auth_request /check;保持一致
@GetMapping("/check")
    public void nginxCheck()
    {
    #此处我只是利用security校验功能,没写具体东西,只打印一句话 说明访问静态资源时,也通过了鉴权才访问的
        System.out.println("nginx 校验");
    }
  1. 修改鉴权部分代码
#说明: 避免验权从header里面去取Authorization,有些时候可能header里面没有携带认证信息,自定义一个存放token保存客户的登录信息放在cookie里面,用于静态资源访问
#1.客户登录之后,在最后设置一个token存放cookie里面
        //设置cookie
        Cookie cookie = new Cookie("check", token);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setSecure(true);
        response.addCookie(cookie);
#2.验权,如果JWT获取不到token,再去取一下自己设置的check下的token
 private String getToken(HttpServletRequest request)
    {
        String token = request.getHeader(token);
        if (Strings.isBlank(token)) {
            Cookie[] cookies = request.getCookies();
            if (cookies != null && cookies.length > 0) {
                for (Cookie cookie : cookies) {
                    if ("check".equals(cookie.getName())) {
                        token = cookie.getValue();
                    }
                }
            }
        }
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
        {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

6.此时重启项目,未登录之前,直接访问静态资源会跳转登录页面,如果登录之后,会进行鉴权获取静态资源(可在鉴权接口里面打印日志进行查看)

一些遇到的问题:

  1. 首先检查一下自己的nginx是否重启成功,遇到过./nginx -s reload 执行后,nginx一些修改没生效问题。
  2. 根据自己服务器是内网还是外网,cookie来设置 cookie.setSecure(true); 因为有些浏览器会在设置cookie是提示尝试通过Set-Cookie标头设置Cookie时被阻止,因为它具有“Secure“属性,但未通过安全连接发送,所以导致再次请求的时候不携带cookie,从而导致认证不通过。