Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring安全性-来自授权服务器的主体不同于资源服务器_Java_Spring_Spring Boot_Spring Security_Spring Security Oauth2 - Fatal编程技术网

Java Spring安全性-来自授权服务器的主体不同于资源服务器

Java Spring安全性-来自授权服务器的主体不同于资源服务器,java,spring,spring-boot,spring-security,spring-security-oauth2,Java,Spring,Spring Boot,Spring Security,Spring Security Oauth2,我在授权服务器中创建了userinfo端点 @GetMapping("/userinfo") public Principal me(Principal principal) { return principal; } 它返回以下JSON: { ... "userAuthentication": { ... "principal": { "id": 2, "username": "xyz",

我在授权服务器中创建了
userinfo
端点

@GetMapping("/userinfo")
public Principal me(Principal principal) {
    return principal;
}
它返回以下JSON:

{
    ...
    "userAuthentication": {
        ...
        "principal": {
            "id": 2,
            "username": "xyz",
            "password": "......",
            "accountNonExpired": true,
            "accountNonLocked": true,
            "credentialsNonExpired": true,
            "enabled": true,
            "authorities": [
                {
                "authority": "ROLE_DONOR"
                }
            ],
            "createdAt": "2019-11-08T20:50:46"
        },
        ...
        "name": "xyz"
    },
    ...
    "principal": {
        "id": 2,
        "username": "xyz",
        "password": "......",
        "accountNonExpired": true,
        "accountNonLocked": true,
        "credentialsNonExpired": true,
        "enabled": true,
        "authorities": [
        {
            "authority": "ROLE_DONOR"
        }
        ],
        "createdAt": "2019-11-08T20:50:46"
    },
    ...
    "name": "xyz"
}
在我的一个资源服务器用户服务API中,我试图
sysout
查看
Principal
的值,只是为了查看它的值:

@GetMapping("/{id}")
public ResourceResponseDto findById(@PathVariable("id") long id, Principal principal) throws IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    String x = objectMapper.writeValueAsString(principal);
    System.out.println(x);
    return ...;
}
principal
的值不同。它的值等于上面的
主体.username
,省略了其他字段:

{
    "userAuthentication": {
        ...
        "principal": "xyz",
        ...
        "name": "xyz"
    },
    ...
    "principal": "xyz",
    ...
    "name": "xyz"
}
这是怎么发生的

我需要得到
id
的值,但它已经不存在了。
principal
object的字段消失了。这会导致我的另一种方法出现错误:

@GetMapping("/{id}")
@PreAuthorize("hasRole('ADMIN') or #id == principal.id")
public ResourceResponseDto findById(@PathVariable("id") long id) {
    //
}
我得到了这个错误

Failed to evaluate expression 'hasRole('ADMIN') or #id == principal.id'

请帮忙。谢谢。

据我所知,您正在实现OAuth2 Spring身份验证服务器。
Principle
只是一个声明方法
getName()
的接口。对于身份验证和资源服务器,
原则
由类
OAuth2Authentication
实现。方法
getPrinciple()


如果OAuth2客户端正在进行身份验证,则它没有
userAuthentication
,只有
clientId
。如果用户正在进行身份验证,您将看到完整的
userAuthentication
对象。

据我所知,您正在实现OAuth2 Spring身份验证服务器。
Principle
只是一个声明方法
getName()
的接口。对于身份验证和资源服务器,
原则
由类
OAuth2Authentication
实现。方法
getPrinciple()


如果OAuth2客户端正在进行身份验证,则它没有
userAuthentication
,只有
clientId
。如果用户正在进行身份验证,则可以从
Authentication.getPrincipal()
文档中看到完整的
userAuthentication
对象。

正在进行身份验证的主体的标识。对于使用用户名和密码的身份验证请求,这将是用户名。调用者需要填充身份验证请求的主体。 AuthenticationManager实现通常会返回 身份验证包含更丰富的信息作为主体供用户使用 应用程序。许多身份验证提供程序将创建一个 UserDetails对象作为主体

因此,您负责在身份验证过程中填充
主体

主体
传递附加信息的方法之一是扩展
用户名密码身份验证筛选器
并重写“attemptAuthentication()”方法:

请注意,将可能包含所需任何数据的
YourObjectForPrincipal
对象作为第一个参数传递给
UsernamePasswordAuthenticationToken
。 要获得扩展用户,只需强制转换到所需对象:

(YourObjectForPrincipal)authentication.getPrincipal();
这可能不是最好的解决方案,但对我来说很有效。
我希望这会有帮助

来自
Authentication.getPrincipal()
文档:

正在进行身份验证的主体的标识。对于使用用户名和密码的身份验证请求,这将是用户名。调用者需要填充身份验证请求的主体。 AuthenticationManager实现通常会返回 身份验证包含更丰富的信息作为主体供用户使用 应用程序。许多身份验证提供程序将创建一个 UserDetails对象作为主体

因此,您负责在身份验证过程中填充
主体

主体
传递附加信息的方法之一是扩展
用户名密码身份验证筛选器
并重写“attemptAuthentication()”方法:

请注意,将可能包含所需任何数据的
YourObjectForPrincipal
对象作为第一个参数传递给
UsernamePasswordAuthenticationToken
。 要获得扩展用户,只需强制转换到所需对象:

(YourObjectForPrincipal)authentication.getPrincipal();
这可能不是最好的解决方案,但对我来说很有效。
我希望这会有帮助

也许已经晚了,但这是我的解决办法。 由于我在我的资源服务器中使用了UserInfoTokenServices,我发现它使用了FixedPrincipalExtractor,在这个类中我看到:

private static final String[] PRINCIPAL_KEYS = new String[] { "user", "username",
            "userid", "user_id", "login", "id", "name" };

    @Override
    public Object extractPrincipal(Map<String, Object> map) {
        for (String key : PRINCIPAL_KEYS) {
            if (map.containsKey(key)) {
                return map.get(key);
            }
        }
        return null;
    }
在这里,我创建了一个UserInfoTokenServices,并设置了我的自定义。不要忘记添加以下属性:

security.oauth2.resource.user-info-uri = http://domain:port/your/user-info-url
security.oauth2.resource.prefer-token-info = false

现在,您可以在资源服务器中获得自己的主体对象。

可能已经晚了,但这是我的解决方案。 由于我在我的资源服务器中使用了UserInfoTokenServices,我发现它使用了FixedPrincipalExtractor,在这个类中我看到:

private static final String[] PRINCIPAL_KEYS = new String[] { "user", "username",
            "userid", "user_id", "login", "id", "name" };

    @Override
    public Object extractPrincipal(Map<String, Object> map) {
        for (String key : PRINCIPAL_KEYS) {
            if (map.containsKey(key)) {
                return map.get(key);
            }
        }
        return null;
    }
在这里,我创建了一个UserInfoTokenServices,并设置了我的自定义。不要忘记添加以下属性:

security.oauth2.resource.user-info-uri = http://domain:port/your/user-info-url
security.oauth2.resource.prefer-token-info = false

现在,您可以在资源服务器中获得自己的主体对象。

首先检查
主体
在每种情况下是什么类。首先检查
主体
在每种情况下是什么类。我会在授权服务器中实现这一点吗?而
YourObjectForPrincipal
指的是我的对象,它包含
id
username
,等等,对吗?@Julez您可以在任意一侧添加它。对于资源服务器,您可以通过AuthorizationServerSecurityConfiger添加它。addTokenEndpointAuthenticationFilter()我创建了一个类,该类使用接受
AuthenticationManager
实例的构造函数扩展
UsernamePasswordAuthenticationFilter
。我将
此.getAuthenticationManager()替换为
此.authenticationManager。
。在我的身份验证服务器配置中,我有以下内容:
authorizationServerSecurityConfiger.addTokenEndpointAuthenticationFilter(新的CustomUsernamePassw
security.oauth2.resource.user-info-uri = http://domain:port/your/user-info-url
security.oauth2.resource.prefer-token-info = false