即使角色匹配且用户凭证正确,在访问SpringBoot中的安全端点时也会获得403

时间:2019-01-14 13:25:15

标签: spring-boot authentication spring-security

下面是“安全性”配置类:-

@EnableWebSecurity
public class SecurityManager extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {

        UserDetails user=User.builder().username("user").password(passwordEncoder().encode("secret")).
                roles("USER").build();
        UserDetails userAdmin=User.builder().username("admin").password(passwordEncoder().encode("secret")).
                roles("ADMIN").build();
        return new InMemoryUserDetailsManager(user,userAdmin);
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/hello*").hasAnyRole("USER","ADMIN");
    }
}  

下面是我正在访问的控制器:

@RestController
public class DemoController {

    @RequestMapping(value="/helloworld",method= RequestMethod.GET)
    public String sampleGetter()
    {
        return "HelloWorld";
    }

    @RequestMapping(value="/helloinnerclass",method= RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
    public InnerClass sampleInnerGetter()
    {
        return new InnerClass("Title","Value");
    }
    class InnerClass
    {
        String title;
        String value;

        public InnerClass(String title, String value) {
            this.title = title;
            this.value = value;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}

当通过Postman触发上述端点时,我得到了403状态代码。下面是错误屏幕截图:-enter image description here

我在项目的属性文件中没有提到任何与安全性相关的内容,因此确保基本安全性不会通过属性文件来处理。

1 个答案:

答案 0 :(得分:0)

您是否尝试过在安全过滤器中启用httpBasic

@Override
protected void configure(HttpSecurity http) throws Exception {
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/hello*").hasAnyRole("USER","ADMIN")
        .and()
        .httpBasic();
}

我创建了一个完整的sample project,同时使用了basic和formLogin

安全配置与您的安全配置类似,但我不希望在实际应用程序中以明文形式显示密码

@Bean
public PasswordEncoder passwordEncoder(){
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
public UserDetailsService userDetailsService() {
    return new InMemoryUserDetailsManager(
        builder()
            .username("user")
            .password("{bcrypt}$2a$10$C8c78G3SRJpy268vInPUFu.3lcNHG9SaNAPdSaIOy.1TJIio0cmTK")
            .roles("USER")
            .build(),
        builder()
            .username("admin")
            .password("{bcrypt}$2a$10$XvWhl0acx2D2hvpOPd/rPuPA48nQGxOFom1NqhxNN9ST1p9lla3bG")
            .roles("ADMIN")
            .build()
    );
}


@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
        //application security
        .authorizeRequests()
            .mvcMatchers("/non-secure/**").permitAll()
            .anyRequest().hasAnyRole("ADMIN","USER")
            .and()
        .httpBasic()
            .and()
        .formLogin()
            .and()
    ;
    // @formatter:on
}

我们可以通过一个simple test案例证明它有效

@Test
@DisplayName("user / 123 basic authentication")
void userBasic() throws Exception {
    mvc.perform(
        get("/secure")
            .header("Authorization", "Basic " + Base64.encodeBase64String("user:123".getBytes()))
    )
        .andExpect(authenticated())
        .andExpect(status().isOk())
    ;
}

我写了一个simple test来对我的密码进行编码

@Test
void printPasswords() {
    System.out.println("123 = "+passwordEncoder.encode("123"));
    System.out.println("password = "+passwordEncoder.encode("password"));
}