Spring 安全 /login - 404 未找到

Spring Security /login - 404 not found

我在启用用户登录页面时遇到问题 - 找不到 404。

这是我用作应用程序安全基础的 tutorial

这就是配置函数的样子:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

我试着简单地在这里添加:

.and()
.formLogin()
.loginPage("/login")
.permitAll();

并将 .addFilter 更改为 .addFilterAfter() 我仍然得到 404。

正如您在教程中看到的那样,这就是访问登录功能的方式:

curl -i -H "Content-Type: application/json" -X POST -d '{
    "username": "admin",
    "password": "password"
}' http://localhost:8080/login

是否可以为此目的启用内置登录表单?

如果不行,有什么解决办法?我是否必须在控制器中创建 /login 端点,然后 POST 数据到 http://localhost:8080/login

然后添加 authenticationFilter 呢?是否必须在那里进行更改?

这里有两个问题:

  1. JWTAuthenticationFilter 扩展自 UsernamePasswordAuthenticationFilter,默认响应 URL /loginformLogin() 也会在此 URL 中生成一个登录表单。因此,您有两个地方接受 /login 的输入。如果您选择自定义登录页面(通过 .loginPage("/login") ),您必须在另一个 URL 中执行此操作,并向该页面提供 HTML 视图。但是你说你想使用内置的登录表单。那么,又来了一个问题:
  2. 要使用内置登录表单,默认情况下必须完成 /login URL,因此您必须更改 de URL JWTAuthenticationFilter。它可以通过在 AbstractAuthenticationProcessingFilter 中设置自定义 URL 来实现,如看到 。这就像一个魅力,但是 JWTAuthenticationFilter 的实现期望作为输入 JSON,/login 表单不提供它(它在 POST).所以你必须更改 JWTAuthenticationFilter.attemptAuthentication 的代码来决定输入是来自 JSON 主体还是参数。

我在我的环境中实现了它并且效果很好。 下面是代码(只是片段):

网络安全:

public JWTAuthenticationFilter getJWTAuthenticationFilter() throws Exception {
    final JWTAuthenticationFilter filter = new JWTAuthenticationFilter(authenticationManager());
    filter.setFilterProcessesUrl("/api/auth/login");
    return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilter(getJWTAuthenticationFilter())
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .formLogin()
            .loginProcessingUrl("/api/auth/login")
            .permitAll();
}

JWTAuthenticationFilter:

@Override
public Authentication attemptAuthentication(HttpServletRequest req,
                                            HttpServletResponse res) throws AuthenticationException {
    try {
        ApplicationUser creds = null;

        if (req.getParameter("username") != null  && req.getParameter("password") != null) {
            creds = new ApplicationUser();              
            creds.setUsername(req.getParameter("username"));
            creds.setPassword(req.getParameter("password"));                
        } else {
            creds = new ObjectMapper()
                    .readValue(req.getInputStream(), ApplicationUser.class);
        }

        return authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        new ArrayList<>())
        );
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}