【问题标题】:spring boot 1.5.4 basic authentication REST API only jsession failsspring boot 1.5.4 基本认证 REST API 只有 jsession 失败
【发布时间】:2017-12-06 22:21:09
【问题描述】:

我正在使用 spring boot 1.5.4 并有一个 sringboot 服务器基本身份验证应用程序。该应用程序的目标是使用凭据登录并使用收到的 jsessionID 来验证对每个额外的 REST API 调用的授权。

在我扩展的 WebSecurityConfigurerAdapter 类中,我的配置方法是:

@Override
protected void configure(HttpSecurity http) throws Exception {
    log.info("In configure");

    http.authorizeRequests()
            .antMatchers("/user/**").permitAll()
            .anyRequest().authenticated()
        //    .antMatchers("/weather/getAll").hasAnyRole("ROLE_USER","ROLE_ADMIN")
            .and().csrf().disable()
            .logout()
            .deleteCookies("JSESSIONID")
            .permitAll();
}

注意:ROLE_USER 和 ROLE_ADMIN 是我在用户表中定义的授权权限。使用 curl 和以下命令进行测试:

>curl -i -d "user=test1&password=test2" http://localhost:8080/user/login -c t1.txt

200 ok 与 JSessionID 一起返回。然后我尝试调用 curl 来获取特定的天气记录,如下所示:

curl -i -v http://localhost:8080/weather/get/760 -b t1.txt Curl 的输出显示登录时收到的 JSessionID 被传递到服务器应用程序。始终返回 403 状态消息。天气get方法如下:

 @PreAuthorize("isAuthenticated()")
@GetMapping("get/{id}")
@JsonIgnore

public ResponseEntity<Weather> get(@PathVariable("id") Integer id){
    Weather weatherData = null;
    log.info("IN weatherTable get ");
    try{
        weatherData =  _weatherDao.getWeatherById(id);
    }catch(Exception e){
        System.out.println("get Exception = "+e.getMessage());
        return null;
    }
    return new ResponseEntity<Weather>(weatherData, HttpStatus.OK);
}

降低了配置覆盖方法的复杂性以尝试排除故障。从 get 方法中删除 Preauthorize 注释确实返回了预期的记录,因此支持代码是正确的。

似乎找不到有助于解释为什么登录中的 JSessionID 值不适用于授权检查的信息/文档。还需要其他步骤吗?任何调试提示将不胜感激。

编辑 添加了这段代码来帮助调试问题:

// @PreAuthorize("hasRole('ROLE_USER')")
    @RequestMapping(value="/getAll")
    @JsonIgnore
    public  ResponseEntity<List<Weather>> getAll(){
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> ga = auth.getAuthorities();
        for (GrantedAuthority granted : ga){
            log.info("AUTHORITY = "+granted.getAuthority());
        }
        List<Weather> weatherData = null;
        try{
            weatherData = _weatherDao.getAll();
        }catch(Exception e){
            System.out.println("getAll Exception = "+e.getMessage());
        }
        return new ResponseEntity<List<Weather>>(weatherData,HttpStatus.OK);
    }

我将 /weather/** 的权限打开到 permitAll() 并使用 ROLE_USER 的用户登录测试。然后使用通过 curl 返回的 cookie 调用 /weather/getAll(见上文)。日志显示此调用的授予权限是“ROLE_ANONYMOUS”。

看起来我遗漏了一些东西来允许跟踪 jsessionid。

【问题讨论】:

    标签: rest spring-boot authorization jsessionid


    【解决方案1】:

    您是否尝试过从authorization rule? 中删除ROLE_

    Spring Security 4 自动为任何角色添加 ROLE_ 前缀。

    在我看来,当 Spring Security 尝试匹配您的角色时,它什么也没找到,并且您收到此 403 错误。

    编辑

    为了说清楚,我的建议是让你的配置规则像这样:

    antMatchers("/weather/getAll").hasAnyRole("USER","ADMIN")
    

    并像现在一样将您的数据保存在数据库中。

    EDIT2:

    hasAnyRolehasAnyAuthority 之间存在差异。引用this blog:

    角色和权限在 Spring 中是相似的。

    主要区别在于,角色具有特殊的语义——从 Spring Security 4 开始,任何与角色相关的方法都会自动添加“ROLE_”前缀(如果还没有的话)。

    所以hasAuthority(‘ROLE_ADMIN’) 类似于hasRole(‘ADMIN’),因为“ROLE_”前缀是自动添加的。

    这就是我要求您从规则中删除 ROLE_ 前缀的原因。

    编辑 3:

    现在我看到你的请求是http://localhost:8080/weather/get/760

    所以你的规则应该是这样的:

    .antMatchers("/weather/get/**").hasAnyAuthority("ROLE_USER","ROLE_ADMIN")

    【讨论】:

    • 使用 PreAuthorize("IsAuthenticated") 作为其余方法?您是否建议修改数据库以从授予的权限值中删除 ROLE?
    • 不!仅从 http.authorizeRequests() 上的配置
    • 刚刚注册了一个角色为 USER 的用户,用该用户登录并获得 200 ok 和 jsessionid。然后让 curl 接听电话并收到 403 返回。将添加一些检查来验证我正在使用的用户信息。
    • 在 te 数据库中将您的用户维护为 ROLE_USER。 Spring 将从您的规则中获取 USER,添加前缀然后匹配。
    • 尝试了 .antmatcher 方法和 PreAuthorize(在配置 .antmatcher 时删除)仍然得到 403。我认为这是角色不匹配。
    猜你喜欢
    • 2020-11-14
    • 2018-02-14
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-26
    相关资源
    最近更新 更多