springSecurityService.principal在tomcat 8.5中作为WAR部署时返回Null

Saq*_*med 7 spring-security tomcat8 spring-security-rest grails3

前言

我正在为Grails微服务联合设计一个API网关.此问题似乎与此存储库中已提交的一系列问题有关,但没有提供解决方案.

版本和配置

Grails:3.2.2

Tomcat:8.5

插件版本:

compile 'org.grails.plugins:spring-security-core:3.1.2'
compile "org.grails.plugins:spring-security-rest:2.0.0.M2"
Run Code Online (Sandbox Code Playgroud)

我正在使用spring security rest插件进行令牌身份验证.我正在通过返回ROLE_NO_ROLES所有用户来自己做授权部分getAuthorities().我拦截所有请求并根据我自己在DB中存储的授权模式授权访问.

问题:

通过这些配置和策略,当我在本地系统上运行时,我的代码可以正常工作.当我在服务器上将其作为war文件在tomcat中部署时,它适用于所有对网关的请求,即对模式的所有请求/umm/controller/action.Spring安全上下文就在那里,用户得到了完美的评估.

当我尝试通过重定向与表单的请求调用其他微服务/umm/microservice/controller/action,springSecurityService.getCurrentUser()springSecurityService?.principal?.username开始返回null.虽然我的令牌得到了完美的评估,但我没有得到任何安全上下文.

有关详细信息,请查看此问题.上述问题中还提供了复制错误的详细信息.整个项目在这里可用.

更新:2017年5月19日

我尝试在我的本地机器上的Tomcat中部署我的战争.这个问题和这个问题提供了以下解决方案

  • 禁用tomcat缓存
  • 设置 grails.plugin.springsecurity.sch.strategyName = org.springframework.security.core.context.SecurityContextHolder.MODE_INHERITABLETHREADLOCAL

到目前为止似乎没有任何工作.无论如何都要SecurityContextHolder回来null了.所有用户检索的功能SpringSecurityService.getCurrentUser(),getPrincipal(),getAuthentication()loadCurrentUser()返回null.

更新:2017年5月23日

为了缩小问题范围,我使用了执行独立战争

java -Dgrails.env=prod -jar build/libs/mywar-0.1.war
Run Code Online (Sandbox Code Playgroud)

现在对于任何非umm请求,我得到一个404, page not found.我认为问题在于生产环境.该应用程序在开发中完全正常.

也试过grails run-app哪个工作正常.为了排除生产环境的问题,我使用grails dev war但无效创建了战争.迄今为止没有任何作品war.

更新:2017年5月25日

我应该问这个http://security.stackexchange.com但是为了记录,我也在这里问它.

我在下面提供的答案包含一个解决方法修复程序.答案中解释了修复工作的机制.我的问题是:

  1. 这种方法是否会在安全系统中引入任何漏洞或漏洞?
  2. 此授权架构是安全还是需要修改?
  3. 我通过插件进行身份验证,但授权自己.有人可以绕过安全过滤器并直接命中授权拦截器吗?因为如果有人能做到这一点,他只需要以与令牌相同的格式给我一个管理员的用户名,他就可以访问所有内容.

Saq*_*med 1

解决方法

我找到了解决该问题的解决方法。由于我只需要用户名,因此我在拦截器中获取了其余令牌,对其进行解码并从中提取用户名。

开始:

def extractUsername(def token){
    Base64 coder = new Base64()
    def tok = token - "Bearer "
    def principal = tok.tokenize(".")
    def dec = coder.decode(principal[1])
    def sub = new String(dec)
    def user = sub.tokenize(",")
    def username=user[1].tokenize(":")
    username = username[1]-"\""
    return username-"\""
}
Run Code Online (Sandbox Code Playgroud)

它对我有用,因为我不需要检查该springSecurityService.Principal对象。如果是这样的话,我就无法获得用户名。springSecurityService.Principal并且springSecurityService.getCurrentUser()仍然返回 null。该问题尚未解决。我之所以回答,是因为尽管有赏金,但我什至没有收到一条评论。如果有人能解释为什么 spring-security-plugin 的行为如此,那么仍然欢迎回答原来的问题

编辑:2017 年 5 月 25 日

我使用的解决方法基于令牌的结构以及用户名嵌入在令牌中并且令牌只是简单地进行 Base64 编码的事实。

这是 spring security REST 插件为 grails 生成的原始令牌:

eyJhbGciOiJIUzI1NiJ9..MPEXURGhJo5s75LfUSm5ckG99Byc7FCLyj1gYZJu1zk

这是解码版本:

“校长”:“H4sIAAAAAAAAAAJVSP0/bQBR/DkFBimgBqZU60KV0qxyJjplISpEqK6kaslCp6GI/3IPznbk7k2SpMpWBAUSLVJWvwDeBhQ9QtUNX5q59ZwhOuyBusfXu59+/57MrmDYaXsaacWH8VGQxl75J NZexwTDT3A79zKCO0OaItRzYpQlcH68EXgAlHllYCLbZHqsJJuNau7eNoa0PNCwrHd8wbmmWYF/pHf+WO1Qa/xEoqL3vJahswDwLQ5VJ21JydZByjdEGzBWzQIU7bvQopBuUljNhJqEVlKwnMAqgyjL7UZE qR2Ph4bXZzHJR66CtBzCTMmPI3X9JOtZZd/fOpqQEu/AJyoPUo0PdPXdQ3/H4TSUEpeZKmqWuTFTEt7gTJ/7R4vHl4emoWwKgTl7c/U0xf9KA0fmHP0/zor3QwuMJ6wWsPkjJzXzBvK7RKf/ 49vbLydX++ylSdojX99/H0spNc8OmSlKmmVUTOyLaftm9E3njbvLxFoZ+hyepQPqjpMXoVqIgprhlrcS4bwuz79rB6marvemeHTepsCjh8lWDpB/kyd3K/EDRwg5+H10cPvtJNG9geo+JDKn4uQLUypIe6 s9nJ4vVr78O8hjjX/ ovxDoTSxYDAAA=”,“子”:“adminDB”,“角色”:[“ROLE_NO_ROLES”],“exp”:1495715793,“iat”:1495712193

这里的主体已签名并加密,但用户名未加密。因此可以通过上面给出的代码轻松提取。