如何在 spring 启动时正确配置 ldap 身份验证?每次我登录时,它都会在调用 /auth 后重定向到 /login

How to properly configure ldap authentication in spring boot? Every time I log in, it redirects to /login after calling /auth

注意 建议的答案无效。

我在 WebSecurityConfigurerAdapter 中有以下配置:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.ldapAuthentication()
            .userSearchBase("somevalue")
            .userSearchFilter("somevalue")
            .contextSource().url("somevalue").port("somevalue")
            .managerDn("somevalue").managerPassword("somevalue");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/*.css", "/*.html", "/*.js", "/*.jpg").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login")
            .loginProcessingUrl("/auth")
            .permitAll();
}

这是我在 WebMvcConfigurer 中的配置:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/*.css", "/*.html", "/*.js", "/*.jpg")
            .addResourceLocations("classpath:/static/");

    registry.addResourceHandler("/", "/login", "/myapp")
            .addResourceLocations("classpath:/static/index.html")
            .resourceChain(true)
            .addResolver(new PathResourceResolver() {
                @Override
                protected Resource getResource(String resourcePath, Resource location) {
                    if (resourcePath.startsWith("/api") || resourcePath.startsWith("/api".substring(1))) {
                        return null;
                    }
                    return location.exists() && location.isReadable() ? location : null;
                }
            });
}

当我点击登录按钮时,我在 angular 中发送了以下请求:

this.http.post(`localhost:8080/auth`, {username: 'user', password: 'password'})...

但我只被重定向到 /login。这是网络控制台:

auth                        302
login                       200

这是请求 (/auth) headers 和 body:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 47
Content-Type: application/json
Cookie: JSESSIONID=*****somecookie*****
Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost:8080/login

有效载荷:

{username: "user", password: "password"}

一般:

Request URL: http://localhost:8080/auth
Request Method: POST
Status Code: 302 
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade

回应headers:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Fri, 01 Mar 2019 10:49:09 GMT
Expires: 0
Location: http://localhost:8080/login
Pragma: no-cache
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

这是它重定向到 /login 的时间:

一般:

Request URL: http://localhost:8080/login
Request Method: GET
Status Code: 200 
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade

要求:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Cookie: JSESSIONID=*****somecookie*****
Host: localhost:8080
Referer: http://localhost:8080/login

基本上,回复body就是我index.html的内容。

并且在控制台中显示:

error: {error: SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse...
headers: e {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:8080/login"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:8080/login"

另外,我的 ldap 配置是否正确? 如何正确配置 ldap 身份验证?

更新 根据建议,我更改了代码以将 body 作为 http 参数发送。现在请求是这样的:

要求Headers: Content-Type: application/x-www.form-urlencoded;charset=UTF-8

表单数据 username=user&password=password

还是一样的问题

我的问题的答案是丢失的 csrf。如果我不禁用 csrf,spring 安全性似乎会寻找它,否则,我的请求将重新路由回登录页面。我通过添加以下内容进行修复:

http.csrf().disable()

对于 /login 期间的 Request method 'POST' not supported,在我的 AuthenticationSuccessHandler.onAuthenticationSuccess() 中,我输入

request.getRequestDispatcher(targetURI).forward(request, response);

相反,我只是用字符串值设置响应:

response.getOutputStream().println(mapper.writeValueAsString(data));