【问题标题】:spring security HTTP Status 403 - Access Deniedspring security HTTP状态403-拒绝访问
【发布时间】:2026-02-15 15:55:02
【问题描述】:

登录成功,但即使我授予了 USER 的访问权限,spring security 也会阻止 url。我该如何管理这件事?

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.inMemoryAuthentication().withUser("sahil").password("123")
                .roles("ADMIN","USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
        .antMatchers("/login").permitAll()
        .antMatchers("/welcome","/inventory/**","/sales/**").access("hasRole('USER')")
        .and()
        .csrf().disable();
    }

LoginController.java

    @Controller
public class LoginController {

    @RequestMapping(value = { "/", "/login" }, method = RequestMethod.GET)
    public String showLoginPage() {
        return "login";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String handleUserLogin(ModelMap model, @RequestParam String name, @RequestParam String password) {
        if (!service.validateUser(name, password)) {
            model.put("errorMsg", "Invalid Credential");
            return "login";
        }
        System.out.println("principal : " + getLoggedInUserName());
        model.put("name", name);
        model.put("password", password);
        return "welcome";
    }

    private String getLoggedInUserName() {

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {
            System.out.println("in if");
          return  ((UserDetails)principal).getUsername();

        } else {
            System.out.println("in else");
         return principal.toString();

        }
    }

    @RequestMapping(value = "/welcome", method = RequestMethod.GET)
    public String showWelcomeDashboard() {
        return "welcome";
    }
}

1 . 一旦登录成功页面重定向到欢迎页面,但 url 仍然是 localhost:8080/login 而不是 localhost:8080/welcome .

2. 重定向到 URL localhost:8080/sales 之后是不是 403 Access denied.

【问题讨论】:

  • 嗨,试着把这个 .access("hasRole('USER')") 改成这个 .access("ROLE_USER")
  • @Error java.lang.IllegalArgumentException: 无法评估表达式'ROLE_USER'
  • @PraveenKumarLalasangi :我已经尝试过了,我添加了更多说明,请您现在查看

标签: java spring spring-mvc spring-security access-denied


【解决方案1】:

什么是弹簧安全
Spring 安全性与身份验证和授权有关,在您的情况下,您缺少身份验证。您的安全配置中没有身份验证配置。您缺少的是用于弹簧安全的身份验证过滤器。 Spring Security 提供了默认的身份验证过滤器UsernamePasswordAuthenticationFilter,可以通过.formLogin() 进行配置。您可以使用默认提供的,也可以定义自己的自定义身份验证过滤器(UsernamePasswordAuthenticationFilter 的实现)。

一旦身份验证成功,spring security 将为经过身份验证的用户授予权限。如果认证配置正确,下面的配置负责认证和授予权限

auth.inMemoryAuthentication().withUser("sahil").password("123")
                .roles("ADMIN","USER");

经过身份验证的用户每个请求都将通过过滤器FilterSecurityInterceptor 传递,它将验证为经过身份验证的用户授予的权限,并为资源配置了如下代码中给出的权限。

.antMatchers("/welcome","/inventory/**","/sales/**").access("hasRole('USER')")

您因未配置身份验证过滤器而错过了所有这些。
现在在你的 http 配置中让它变得简单 use.formLogin() 。

@Override
protected void configure(final HttpSecurity http) throws Exception
{
    http
    .authorizeRequests()
        .antMatchers("/welcome","/inventory/**","/sales/**").access("hasRole('USER')")
    .and().exceptionHandling()
        .accessDeniedPage("/403")
    .and().formLogin()
    .and().logout()
        .logoutSuccessUrl("/login?logout=true")
        .invalidateHttpSession(true)
    .and()
        .csrf()
            .disable();
}

.formLogin() 没有任何配置提供默认登录页面,用户名和密码默认表单参数。身份验证后重定向到"/" 如果您想提供自定义登录页面,请使用以下配置。

.and().formLogin()
       .loginPage("/login")
       .usernameParameter("email").passwordParameter("password")
       .defaultSuccessUrl("/app/user/dashboard")
       .failureUrl("/login?error=true")

.loginPage("") - 您的自定义登录页面 URL
.usernameParameter("").passwordParameter("") - 您的自定义登录表单参数
.defaultSuccessUrl("") - 身份验证成功后的页面 URL
.failureUrl("") - 身份验证失败后的页面 URL

注意:你不应该在你的控制器中使用“/login” POST方法,即使你写了,它也不会从spring安全过滤器链中到达。由于您之前的配置是错误的,它之前达到了!现在你从你的控制器中删除它们并使用上面提到的传统方法。

【讨论】:

  • @PraveenKumarLalasangi 很好的解释。你能分享你学习spring boot的资源吗?我对弹簧靴很陌生,只有弹簧芯的基本知识。
  • 谢谢,Spring boot 和传统的 Spring-mvc 没有区别,除了 spring boot 带有默认的自动配置,我没有从任何教程中学习过 spring,但我要做的是我会去 spring 文档并参考并实现我所需要的。在 spring/spring security 工作时,启用调试日志和分析日志帮助我理解了内部架构。仍然每天都在学习,有时我们可能理解错了,所以每次交叉检查概念与实际实现都会清除概念并帮助我理解。
  • 我写答案来分析自己,期待有人会指出我的错误并通知我。或者有人会编写替代方法,这也有助于我学习。