Java 使用自定义身份验证理解spring安全中的“拒绝访问”

Java 使用自定义身份验证理解spring安全中的“拒绝访问”,java,spring,spring-security,authorization,Java,Spring,Spring Security,Authorization,我正在努力掌握Spring的安全性和可用性 经过相当多的工作和帮助,我能够在SpringSecurity中实现一些自定义身份验证机制,但现在我有一些授权问题,我真的不太明白 如果我向localhost:8080/login?username=admin&password=sesamoeffendech&secondSecret=youNeedMe发出POST请求,我将收到403拒绝访问 如果有人能解释原因,我将不胜感激 我的配置如下: @Configuration @EnableWebSecur

我正在努力掌握Spring的安全性和可用性 经过相当多的工作和帮助,我能够在SpringSecurity中实现一些自定义身份验证机制,但现在我有一些授权问题,我真的不太明白

如果我向localhost:8080/login?username=admin&password=sesamoeffendech&secondSecret=youNeedMe发出POST请求,我将收到403拒绝访问

如果有人能解释原因,我将不胜感激

我的配置如下:

@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan
public class AppConfig extends WebSecurityConfigurerAdapter
{
    @Autowired
    MyAuthenticationProvider myAuthenticationProvider;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
                .authorizeRequests().antMatchers("/**")
                    .hasAnyRole()
                    .anyRequest()
                    .authenticated()
                    .and()
                .csrf().disable()
                .httpBasic().disable();
    }

    @Bean
    public AuthenticationManager authenticationManager(){
        return new ProviderManager(Arrays.asList(myAuthenticationProvider));
    }

    @Bean
    public ViewResolver viewResolver()
    {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
我认为通过这种配置,授权机制将自动授予访问权限,因为[…]

这是我的令牌实现;为了练习,我想保持它的简单;如果需要理解实现的任何其他部分,请告诉我,我会提供它,但我不想一开始就用太多不必要的代码淹没帖子:

public class MyAuthenticationToken implements Authentication {
    public static final String SECOND_SECRET = "youNeedMe";
    private final String principalName;
    private MyCredentials credentials;
    private boolean authenticated;

    public MyAuthenticationToken(String principalName, MyCredentials credentials) {
        this.principalName = principalName;
        this.credentials = credentials;
    }
    //Everyone is admin for the sake of the example
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        LinkedList<GrantedAuthority> authorities = new LinkedList<>();
        authorities.add(new SimpleGrantedAuthority("ADMIN"));
        return authorities;
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    @Override
    public Object getDetails() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.principalName;
    }

    @Override
    public boolean isAuthenticated() {
        return this.authenticated;
    }

    @Override
    public void setAuthenticated(boolean b) throws IllegalArgumentException {
        this.authenticated = b;
    }

    @Override
    public String getName() {
        return this.principalName;
    }
}
以及:


为了处理您的问题,我需要MyAuthenticationFilter和MyAuthenticationProvider的源代码。但我有一个以前实施过的更好的解决方案,您可以在my github上找到一个完全可行的spring安全示例,该示例配置了自定义身份验证和基于RBAC角色的访问控制授权:

我希望这对你有帮助

我的网络配置或如您所说的AppConfig来源:

@Configuration
@EnableWebMvc
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        prePostEnabled=true,
        securedEnabled=true,
        jsr250Enabled=true)
public class WebConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

    @Override
    protected void configure(HttpSecurity http) throws Exception {      
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            .and().csrf().disable();
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowCredentials(true)
        .allowedHeaders("*")
        .allowedMethods("GET, POST, PATCH, PUT, DELETE, OPTIONS")
        .allowedOrigins("*");
    }

    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver resolver= new InternalResourceViewResolver();
        resolver.setPrefix("/jsp/");
        resolver.setSuffix(".jsp");
        return resolver;
    }  

    @Bean
    public ErrorPageFilter errorPageFilter() {
        return new ErrorPageFilter();
    }
}
客户身份验证的来源:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    public CustomAuthenticationProvider() {
        super();
    }

    // API

    @Override
    public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
        final String name = authentication.getName();
        final String password = authentication.getCredentials().toString();
        final List<GrantedAuthority> grantedAuths = new ArrayList<>();

        if(!(name.equals("admin") && password.equals("admin")) && 
                !(name.equals("user") && password.equals("user")))
            throw new RuntimeException("username or password is incorrect");
        if(name.equals("admin"))
        {
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        else
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));

        final UserDetails principal = new User(name, password, grantedAuths);
        final Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths);
        return auth;

    }

    @Override
    public boolean supports(final Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}
或者用最简单的方法取下你的蚂蚁匹配器**:

    http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .httpBasic().disable();
事实上,如果您想要角色检查,那么在登录服务上检查角色并不是一个好主意,最好先让用户登录,然后再进一步请求检查其他特定的antMatcherUrl角色

同时,您可以使用@Secured进行角色授权

为了安全保证,我在登录前和登录后都添加了Hello服务,以确保安全异常的确定性

@RestController("/hello")
public class HelloService {

    @GetMapping
    public String get()
    {
        return "Hello there!";
    }

}

为了处理您的问题,我需要MyAuthenticationFilter和MyAuthenticationProvider的源代码。但我有一个以前实施过的更好的解决方案,您可以在my github上找到一个完全可行的spring安全示例,该示例配置了自定义身份验证和基于RBAC角色的访问控制授权:

我希望这对你有帮助

我的网络配置或如您所说的AppConfig来源:

@Configuration
@EnableWebMvc
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        prePostEnabled=true,
        securedEnabled=true,
        jsr250Enabled=true)
public class WebConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

    @Override
    protected void configure(HttpSecurity http) throws Exception {      
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            .and().csrf().disable();
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowCredentials(true)
        .allowedHeaders("*")
        .allowedMethods("GET, POST, PATCH, PUT, DELETE, OPTIONS")
        .allowedOrigins("*");
    }

    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver resolver= new InternalResourceViewResolver();
        resolver.setPrefix("/jsp/");
        resolver.setSuffix(".jsp");
        return resolver;
    }  

    @Bean
    public ErrorPageFilter errorPageFilter() {
        return new ErrorPageFilter();
    }
}
客户身份验证的来源:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    public CustomAuthenticationProvider() {
        super();
    }

    // API

    @Override
    public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
        final String name = authentication.getName();
        final String password = authentication.getCredentials().toString();
        final List<GrantedAuthority> grantedAuths = new ArrayList<>();

        if(!(name.equals("admin") && password.equals("admin")) && 
                !(name.equals("user") && password.equals("user")))
            throw new RuntimeException("username or password is incorrect");
        if(name.equals("admin"))
        {
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        else
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));

        final UserDetails principal = new User(name, password, grantedAuths);
        final Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths);
        return auth;

    }

    @Override
    public boolean supports(final Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}
或者用最简单的方法取下你的蚂蚁匹配器**:

    http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .httpBasic().disable();
事实上,如果您想要角色检查,那么在登录服务上检查角色并不是一个好主意,最好先让用户登录,然后再进一步请求检查其他特定的antMatcherUrl角色

同时,您可以使用@Secured进行角色授权

为了安全保证,我在登录前和登录后都添加了Hello服务,以确保安全异常的确定性

@RestController("/hello")
public class HelloService {

    @GetMapping
    public String get()
    {
        return "Hello there!";
    }

}

非常感谢链接进一步参考!不过我还是想知道我的误解在哪里,以便更好地理解。我补充了你所要求的消息来源。@Wolfone我很乐意。我更新了答案,请查收。谢谢,很抱歉回复晚了!非常感谢链接进一步参考!不过我还是想知道我的误解在哪里,以便更好地理解。我补充了你所要求的消息来源。@Wolfone我很乐意。我更新了答案,请查收。谢谢,很抱歉回复晚了!