基于Nginx+Lua实现的Token鉴权认证

一、问题描述:

1、管理员发布页面流程:

1

2、用户访问页面流程:

2

3、遇到了哪些难题?

3

管理员要发布一个公告,在前台发送post请求,携带需要发布的json数据,调用后台api服务,通过需要发布的数据,利用Freemaker模板,生成一个静态页,保存到服务器指定目录。

所以,一个静态页面,无论非登录用户还是已登录但是没有授予查看该稿件权限的用户,页面能够做的是利用JS判断他们的用户类型,是否具有查看稿件角色权限,如果没有则隐藏静态数据,提示相关信息,拒绝他们查看。

这对于非法用户来说,相当危险,他们可以通过查看网页源代码,找到当前隐藏的Input标签,从而获取数据。

另外,通过爬虫也可以直接爬取所有包含敏感信息的页面的数据。

所以,需要思考该怎么样,在页面访问之前,拦截到非法用户,直接拒绝他们访问,跳转到相关页面,不让他们窃取数据。

二、解决思路及方案?

解决方案:

利用Nginx+Lua,做一个Token鉴权模块,拦截访问以.shtml结尾的页面,根据用户类型调用后台鉴权接口,的带返回类型后,再跳转到当前用户可以查看的页面。

实现思路:

前提:用户登录后,会在Cookie里存储Token
Key为unit_token
value=token的值
(各位可根据实际情况修改Lua获取Token值的方式)

(1)用户在访问页面时,首先经过Nginx,我们可以在Nginx设置location匹配值,.shtml结尾的页面走指定Lua脚本。

(2)在Lua脚本中,获取到用户访问的地址,截取.shtml结尾前的字符串,有可能为空(首页),index,list,或者具体某个稿件(UUID), 如 http://localhost:8080/jdgg/jdqx/1216721652781.shtml ,我们截取到具体稿件id:1216721652781
并检测请求头中是否存有Token(用户登录后会将Token存储到Cookie中,每次用户访问时请求头会携带Cookie中的Token
整理请求格式
http://127.0.0.1:8282/api/front/jurisdiction/content?contentId=1216721652781,发送到后台进行鉴权。

(3)如果后台鉴权没有调用成功(服务器崩了,或者状态码非200),利用Lua跳转到503页面,给用户提示:内部服务器错误。

(4)如果后台鉴权接口调用成功,则根据返回的参数决定跳转到哪个页面。

好处:

无需修改静态页面,无论什么样的用户访问,都可以根据用户类型跳转到指定页面,防止非法用户爬取数据,或者通过查看网页源代码查看敏感数据。

三、目前该模块所做到的事情有哪些?

分为向所有人员公开的网站,及内部人员才可以访问的网站。

公开网站(hlw_nginx.conf && hlw_dev.lua):

后台鉴权地址返回值: true or false

安全模块需求:

(1)允许所有用户访问:首页,及各个子栏目列表页 (军队需求列表页,军工需求列表页等等),及一些通用模块(footer.shtml ->{用来点击下一页,上一页等等})

(2)允许部分用户访问(在调用后台鉴权接口成功后):

返回false:跳转到401(未授权页面)

返回true: 表示允许用户访问

(3)调用后台鉴权接口失败:

返回值状态码非200: 跳转到503页面(内部服务器错误)

请求超时(可能服务器挂了) 跳转到503页面

涉密网站(sm_nginx.conf && sm_dev.lua):

安全模块需求:

(1)当用户访问任意一个页面时,如果未登录,直接跳转到登录页

(2)如果用户已登录,在访问任意一个页面时,会将参数(稿件Id + Token)传递并调用后台鉴权接口判断

如果返回3-> 未授权,则跳转到401页面

如果返回2-> 用户未登录,跳转到登录页

如果返回1-> 允许用户访问

(3)调用后台鉴权接口失败:

返回值状态码非200: 跳转到503页面(内部服务器错误)

请求超时(可能服务器挂了) 跳转到503页面

后台使用SpringBoot接收:

(1)公开网站:

@RequestMapping(value = "/content",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("稿件查看权限校验")
    public boolean contentJurisdiction(@RequestParam("contentId")String contentId,
                                       @RequestParam(name = "token",defaultValue = "0")String token){
        ContentDatabaseEntity entity = contentDatabaseServiceI.selectContentByContentId(contentId);
        if (null == entity){
            return false;
        }
        Map json = (Map) JSON.parse(entity.getDocextendjson());
        Map content = (Map) JSON.parse(json.get("json").toString());
        if (content.containsKey("publicType")){
            //2  仅供企事业认证用户查看
            if ("2".equals(content.get("publicType").toString())){
                //无token 未登录
                if ("0".equals(token)){
                    return false;
                }else {
                    //去unit校验token
                    String result = contentDatabaseServiceI.checkToken(token);
                    if ("allow".equals(result)){
                        return true;
                    }
                    return false;
                }
            }
        }
        return true;
    }

(2)涉密网站:

@RequestMapping(value = "/content",method = RequestMethod.GET)
@ResponseBody
@ApiOperation("稿件查看权限校验")
public Integer contentJurisdiction(@RequestParam(name = "contentId",defaultValue = "0")String contentId,
                                   @RequestParam(name = "token",defaultValue = "0")String token){
    //需求不同,SM内网必须登录才能查看HTML内容
    if ("0".equals(token)){
        return 2;
    }
    //校验token SM特殊需求
    String result = contentDatabaseServiceI.checkToken(token);
    //如果没有contentID并且token校验通过 返回
    if ("0".equals(contentId)){
        if ("invalid".equals(result)){
            return 2;
        }
        return 1;
    }
    ContentDatabaseEntity entity = contentDatabaseServiceI.selectContentByContentId(contentId);
    if (null == entity){
        return 3;
    }
    Map json = (Map) JSON.parse(entity.getDocextendjson());
    Map content = (Map) JSON.parse(json.get("json").toString());
    if (content.containsKey("publicType")){
        //2  仅供企事业认证用户查看
        if ("2".equals(content.get("publicType").toString())){
            //去unit校验token
            if ("allow".equals(result)){
                return 1;
            }
            return 3;

        }
    }
    return 1;
}

具体代码请查看我的Github地址:

https://github.com/1170159634/PageSafetyCertification/

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值