Nginx 使用 auth_request 实现公司内网的飞书授权登录

1,125 阅读3分钟

什么是 auth_request:

image.png 用官网的的话来简单描述就是 根据子请求的结果实现客户端授权。如果子请求返回 2xx 响应代码,则允许访问。如果返回 401 或 403,则使用相应的错误代码拒绝访问,那么我们就可以根据这个特性,使用一个授权接口对用户的 飞书 | 其他第三方或者 oauth 登录做登录状态校验,如果登录了,直接 200OK 放行通过,如果授权不通过,那么返回 401 or 403 ,再通过 nginx 做状态拦截转发,那么就可以引导到 授权页面,进行登录,从而实现 使用 飞书 授权来进行登录态拦截和放行的操作

**那么我们实现 auth_request 需要一下几部操作 **

1、检查nginx版本,并查看有没有 ## auth_request 的功能

nginx -V image.png 如果没有 auth_request 的话,那么请 升级 nginx 版本

2、编写 nginx 相关模块

location = /auth {  
    internal;  
    # proxy_pass 用于 auth 的校验接口
    proxy_pass http://ip:port/your/auth 
    proxy_pass_request_body off;  
    proxy_set_header Cas-Host $host;  
    proxy_set_header X-Real-IP $remote_addr;  
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
    proxy_set_header X-Original-URI $request_uri;  
    proxy_set_header X-Forwarded-Proto https;  
    proxy_set_header Content-Length "";  
}

# 鉴权失败时候的 401 拦截页面,通过 302 跳转到详情的 feishu_oauth 授权页面,在通过授权成功之后 跳转回到 state 原页面
error_page 401 /auth_401.html;  
location = /auth_401.html {  
    return 302 $feishu_oauth_uri&state=https://$host$request_uri;  
}

# 其他模块中的 的 nginx 配置,只需要添加 auth_request /auth;  即可实现拦截
location /other {  
    auth_request /auth;  
    proxy_set_header Host $host;  
    proxy_set_header X-Real-IP $remote_addr;  
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
    proxy_read_timeout 300s;  
    proxy_pass http://other/index;  
}

其中 401 转发 302 的 feishu_oauth_uri = 飞书的授权链接 passport.feishu.cn/suite/passp…

注意: /auth 中proxy_pass 配置 之前是没使用 IP 而使用域名的时候,nginx 一直报错

image.png 不知道是不是 本身 域名 + nginx + lb 导致的,反正没找到原因,改成IP 后 一切正常

3、编写 auth 相关的 授权接口

image.png auth 通过 cookie 里面的 登录信息判断是否登录 登录?返回 200 OK : 401 Unauthorized

image.png 该代码为飞书回调请求地址,获取到登录 code -> 拿取用户信息 -> 存放到 cookie -> 存到本地缓存当中 -> 跳转到 success.html 页面,进行定时调整到请求 state 的 url 当中,从而实现回调回转

其中 LarkHelper + Cache 使用的是这个 guava cache + larksuite.opai

image.png

image.png 授权需要注意的点就是,/login 是飞书的授权回调,授权回调会给你一个 code ,但是 code 只能使用一次,就会失效,所以这里,再授权回调的接口当中,通过 code 获取飞书的登录信息,然后进行 UUID 转化,之后 存到 cookie 当中,这样的话,前端页面再次访问的时候,就会带上这个 cookie,在根据本地缓存判断有没有,这样就可以实现 用户是否登录的校验

4、前端页面

image.png 注意: 前端页面使用 thymeleaf 技术来接受 后端 ModelAndView 传过来的 state 调整链接

相关配置:

image.png

image.png

5、飞书配置

当你实现了所有这些,可能会出现一些其他的问题,可能是 飞书的配置没有配置

配置链接:open.feishu.cn/app?lang=zh…

1、没有权限

image.png

未配置 成员管理:

image.png

2:授权页面 4401

image.png client_id 错误 或者 redirect_uri 授权回调地址公网不能防卫,或者安全设置未设置

image.png

image.png

6:实现效果

image.png

7: 问题总结

1:URL 参数被截断

我们可以使用 nginx 的 openresty 中的 nginx-plus-module-set-misc 对 url 进行 base64 编码 或者 写 lua 脚本实现。也可以使用中转页 对 URL 进行 获取,并进行 base64 编码

总结:

出错的问题,一般在 nginx 配置,如果 curl 所有接口访问通畅,nginx 配置正确,一般不会有其他问题了