当前位置: 首页 > 知识库问答 >
问题:

Spring MVC webapp+REST:授权问题

曹景铄
2023-03-14

我正在用Spring MVC构建一个CRM系统。现在我为系统添加了REST支持,但是Spring Security出于某种原因将允许角色为“employee”的未经授权的用户访问POST方法(在系统中创建一个新客户)。在表单和身份验证方面,一切都能正常工作。只是由于某种原因授权失败,特别是对于RESTController。

我使用PostgreSQL存储客户和用户,并进行身份验证。

注意:我使用“/customer”作为REST和webapp表单的入口点。

这是我的SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers(HttpMethod.GET, "/customer").hasRole("EMPLOYEE")
            .antMatchers(HttpMethod.POST, "/customer").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/showForm*").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/save*").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/delete").hasRole("ADMIN")
            .antMatchers("/customer/**").hasRole("EMPLOYEE")
            .antMatchers("/resources/**").permitAll()
            .and()
            .httpBasic()
            .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/authenticate")
            .permitAll()
            .and()
            .logout().permitAll()
            .and()
            .exceptionHandling().accessDeniedPage("/access-denied")
            .and()
            .csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }
}
@RestController
@RequestMapping("/customer")
public class CustomerRestController {

    @Autowired
    private CustomerService customerService;

    @GetMapping
    public List<Customer> getCustomers() {
        return customerService.getCustomers();
    }

    @GetMapping("/{customerId}")
    public Customer getCustomer(@PathVariable int customerId) {
        Customer customer = customerService.getCustomer(customerId);
        if (customer == null) throw new CustomerNotFoundException("Customer not found: id = " + customerId);
        return customer;
    }

    @PostMapping
    public Customer addCustomer(@RequestBody Customer customer) {
        customer.setId(0);
        customerService.saveCustomer(customer);
        return customer;
    }
}
    null

共有1个答案

仲孙宇定
2023-03-14

经过几个小时的研究和反复试验,一切都按预期进行。关键问题是方法路径中缺少星号。它必须是“/customer/**”,而不是“/customer”。我还对web表单和REST支持的路径进行了一点更改,以避免混乱,并使支持更加容易。无论如何,以下是更新后的SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

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

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }

    @Configuration
    @Order(1)
    public static class ApiSecurityConfig extends WebSecurityConfigurerAdapter {

        @Bean
        public AuthenticationEntryPoint entryPoint() {
            return new CustomAuthenticationEntryPoint();
        }

        @Bean
        public AccessDeniedHandler accessDeniedHandler() {
            return new CustomAccessDeniedHandler();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().antMatcher("/api/**")
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/api/customers/**").hasRole("EMPLOYEE")
                .antMatchers(HttpMethod.POST, "/api/customers/**").hasAnyRole("MANAGER", "ADMIN")
                .and()
                .httpBasic()
                .authenticationEntryPoint(entryPoint())
                .and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    }

    @Configuration
    @Order(2)
    public static class FormSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                .antMatchers("/customer/showForm*").hasAnyRole("MANAGER", "ADMIN")
                .antMatchers("/customer/save*").hasAnyRole("MANAGER", "ADMIN")
                .antMatchers("/customer/delete").hasRole("ADMIN")
                .antMatchers("/customer/**").hasRole("EMPLOYEE")
                .antMatchers("/resources/**").permitAll()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/authenticate")
                .permitAll()
                .and()
                .logout().permitAll()
                .and()
                .exceptionHandling().accessDeniedPage("/access-denied");
        }
    }
}
 类似资料:
  • 我试图用Github Api做一个授权请求,传递用户名和密码。但它不起作用,我得到了401状态代码。 文件里有一部分说 这是我的密码:

  • 问题内容: 我正在为iOS 8开发一个Swift代码。我正在尝试做一些涉及位置的事情,因此我在swift视图控制器文件中实现了以下内容: 但是,我似乎无法使此代码正常工作。它不会保存我对位置使用的偏好。它甚至不提示我允许访问位置。我尝试更新我的info.plist。但这不起作用。顺便说一句,如果我始终在模拟器的隐私设置中选择,那么如果我立即切换回该应用程序,它将起作用。有人可以帮忙吗?我确定那是问

  • 在spotify api的授权步骤中,我完全迷失了方向 我需要提出一个类似于邮递员的请求: 具有包含client_id和client_secret(api 凭据)的标头 这些是根据授权流完成的(在他们的授权指南中的第四个-(隐式授权流(客户凭证流))本页最后一个:https://developer.spotify.com/documentation/general/guides/authoriza

  • 我正在为Cosmos DB Table API尝试rest-from-. net。 设置、、、。我正在使用内部资源ID。设置为2017-07-29。 在第 84 行之前添加了以下内容。 现在,它看起来像下面: 在<code>GetStringAsync<code>调用中,我得到401。 > 我在Azure Cosmos DB帐户上具有参与者角色。 我已经浏览了这篇文章 关于堆栈溢出. 使用REST

  • 我想从我的android应用程序中读取来自Google Sheets的表格。我想通过Google Sheets API来做到这一点。我将工作表声明为公共,创建了API密钥并尝试发送服务调用: 我有401密码。答复: 请求缺少必需的身份验证凭据。需要OAuth 2访问令牌、登录cookie或其他有效的身份验证凭据。看见https://developers.google.com/identity/si

  • 我想更好地理解隐式授权流和授权代码授权流之间的区别,因为我不确定我目前的理解是否正确。 隐式授权流主要由前端应用程序用于验证用户身份吗? 隐式授权流是否只需要一个client_id、用户名和密码来进行身份验证,换句话说,永远不会发送client_secret? 授权码只是一个短期令牌吗? 将授权码交换为访问令牌后,客户端可以访问用户帐户多长时间?具体地说,如果客户端是一个长时间运行的脚本,那么用户