【问题标题】:Restful LDAP Authentication Service using springboot使用 Spring Boot 的 Restful LDAP 身份验证服务
【发布时间】:2020-01-04 06:05:36
【问题描述】:

我正在编写一个程序来验证通过 HTTP POST 发送的用户名和密码,并针对 ldap 进行验证,并将响应发送回用户,无论验证是否成功。

我的网络安全配置器实现

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;

import org.springframework.boot.autoconfigure.security.SecurityProperties;

@Configuration
@Order(SecurityProperties.IGNORED_ORDER)
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
        http.csrf().disable();

    }

    @SuppressWarnings("deprecation")
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .ldapAuthentication()
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource()
                    .url("ldap://localhost:8389/dc=springframework,dc=org")
                    .and()
                .passwordCompare()
                    .passwordEncoder(new LdapShaPasswordEncoder())
                    .passwordAttribute("userPassword");
    }

}

我的 test-server.ldif

dn: dc=springframework,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: springframework

dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups

dn: ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: subgroups

dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people

dn: ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: space cadets

dn: ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: "quoted people"

dn: ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: otherpeople

dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=

dn: uid=bob,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: bobspassword
.
.

我在 application.properties 中也定义了这个。 spring.ldap.embedded.ldif=classpath:test-server.ldif

我正在尝试从邮递员那里发布数据,并且我收到任何值的 403 响应。

我无法弄清楚为什么它会给出 403。 谁能理解我做错了什么。谢谢。

以下是更新的安全日志:

2019-09-03 10:11:56.942 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 1 附加过滤器链中的 10 个;发射过滤器: 'WebAsyncManagerIntegrationFilter' 2019-09-03 10:11:56.944 调试 9040 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /rest/hello 位于附加过滤器链中第 10 位的第 2 位;射击 过滤器:'SecurityContextPersistenceFilter' 2019-09-03 10:11:56.944 调试 9040 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : 当前没有 HttpSession 存在于 2019-09-03 10:11:56.945 调试 9040 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : 没有 SecurityContext 可从 HttpSession 获得:null。将创建一个新的。 2019-09-03 10:11:56.947 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 3 附加过滤器链中的 10 个;触发过滤器:'HeaderWriterFilter' 2019-09-03 10:11:56.948 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 4 附加过滤器链中的 10 个;触发过滤器:'LogoutFilter' 2019-09-03 10:11:56.948 调试 9040 --- [nio-8080-exec-2] os.s.web.util.matcher.OrRequestMatcher :尝试使用 Ant 进行匹配 [pattern='/logout', GET] 2019-09-03 10:11:56.949 调试 9040 --- [nio-8080-exec-2] os.s.w.u.matcher.AntPathRequestMatcher:检查 请求匹配:'/rest/hello';反对“/注销” 2019-09-03 10:11:56.949 调试 9040 --- [nio-8080-exec-2] os.s.web.util.matcher.OrRequestMatcher :尝试使用 Ant 进行匹配 [pattern='/logout', POST] 2019-09-03 10:11:56.949 调试 9040 --- [nio-8080-exec-2] os.s.w.u.matcher.AntPathRequestMatcher:请求 'GET /rest/hello' 与 'POST /logout' 不匹配 2019-09-03 10:11:56.949 调试 9040 --- [nio-8080-exec-2] os.s.web.util.matcher.OrRequestMatcher :尝试使用 Ant 进行匹配 [pattern='/logout', PUT] 2019-09-03 10:11:56.950 调试 9040 --- [nio-8080-exec-2] os.s.w.u.matcher.AntPathRequestMatcher:请求 'GET /rest/hello' 不匹配 'PUT /logout' 2019-09-03 10:11:56.950 调试 9040 --- [nio-8080-exec-2] os.s.web.util.matcher.OrRequestMatcher :尝试使用 Ant 进行匹配 [pattern='/logout', DELETE] 2019-09-03 10:11:56.950 调试 9040 --- [nio-8080-exec-2] os.s.w.u.matcher.AntPathRequestMatcher:请求 “GET /rest/hello”与“DELETE /logout”不匹配 2019-09-03 10:11:56.950 调试 9040 --- [nio-8080-exec-2] os.s.web.util.matcher.OrRequestMatcher:未找到匹配项 2019-09-03 10:11:56.951 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 5 附加过滤器链中的 10 个;发射过滤器: 'RequestCacheAwareFilter' 2019-09-03 10:11:56.951 调试 9040 --- [nio-8080-exec-2] os.s.w.s.HttpSessionRequestCache :已保存 请求不匹配 2019-09-03 10:11:56.951 DEBUG 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 位于附加过滤器链中第 10 位的第 6 位;射击 过滤器:'SecurityContextHolderAwareRequestFilter' 2019-09-03 10:11:56.953 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 7 附加过滤器链中的 10 个;发射过滤器: 'AnonymousAuthenticationFilter' 2019-09-03 10:11:56.958 调试 9040 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter :已填充 带有匿名令牌的 SecurityContextHolder: 'org.springframework.security.authentication.AnonymousAuthenticationToken@938ad544: 委托人:anonymousUser;凭证:[受保护];已认证: 真的;细节: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: 远程IP地址:0:0:0:0:0:0:0:1;会话ID:空;的确 权威:ROLE_ANONYMOUS' 2019-09-03 10:11:56.958 DEBUG 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 位于附加过滤器链中 10 个位置的第 8 位;射击 过滤器:'SessionManagementFilter' 2019-09-03 10:11:56.958 DEBUG 9040 --- [nio-8080-exec-2] o.s.s.w.session.SessionManagementFilter :请求的会话 ID 84F3D9D1165FFEE7008EDB2FA99B0D88 无效。 2019-09-03 10:11:56.958 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在位置 9 附加过滤器链中的 10 个;发射过滤器: 'ExceptionTranslationFilter' 2019-09-03 10:11:56.959 调试 9040 --- [nio-8080-exec-2] os.security.web.FilterChainProxy : /rest/hello 在附加过滤器链中的第 10 个位置(共 10 个);射击 过滤器:'FilterSecurityInterceptor' 2019-09-03 10:11:56.960 DEBUG 9040 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor:安全对象:FilterInvocation:URL:/rest/hello;属性: [已验证] 2019-09-03 10:11:56.960 调试 9040 --- [nio-8080-exec-2] os.s.w.a.i.FilterSecurityInterceptor : 之前认证: org.springframework.security.authentication.AnonymousAuthenticationToken@938ad544: 委托人:anonymousUser;凭证:[受保护];已认证: 真的;细节: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: 远程IP地址:0:0:0:0:0:0:0:1;会话ID:空;的确 权威机构:ROLE_ANONYMOUS 2019-09-03 10:11:56.972 DEBUG 9040 --- [nio-8080-exec-2] os.s.access.vote.AffirmativeBased :选民: org.springframework.security.web.access.expression.WebExpressionVoter@136951e, 返回:-1 2019-09-03 10:11:56.983 DEBUG 9040 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter :访问被拒绝(用户是 匿名的);重定向到身份验证入口点

org.springframework.security.access.AccessDeniedException: 访问是 拒绝 在 org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) ~[spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) [spring-web-5.1.8.RELEASE.jar!/:5.1.8.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) [spring-web-5.1.8.RELEASE.jar!/:5.1.8.RELEASE] 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] 在 org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]

【问题讨论】:

  • 设置 spring 安全日志来调试然后运行它,它会告诉你它在 stackoverflow.com/questions/20485059/… 上失败的原因
  • 感谢 thomas 的回复,我已经更新了日志
  • 你在跟踪什么?
  • 在上面的描述中更新了它们
  • 再次阅读我的问题,你在跟踪什么日志,看起来你在跟踪日志 spring web 我想查看 spring 安全的调试日志logging.level.org.springframework.security=DEBUG

标签: spring-boot ldap restful-authentication spring-security-ldap


【解决方案1】:

如果没有任何日志和可能更多的代码,就不可能提供明确的答案。但我有一些提示:

  • 示例凭据与您显示的示例 ldif 不匹配。也许有错误?

  • 您似乎在使用自己的入口点。目前尚不清楚它应该如何工作,但是将带有凭据的 JSON 正文发布到似乎是安全的应用程序 URL 似乎并不正确。它可能会导致向不应接收敏感信息的端点发送凭据。也许您最好使用标准身份验证机制

  • 密码比较不如使用 LDAP 绑定身份验证安全和灵活。它仅支持不再被认为是安全的有限密码哈希算法,并且在密码加盐的情况下,需要从 LDAP 条目中检索密码。 LDAP 绑定支持 LDAP 服务器支持的任何散列算法,现有密码永远不需要离开 LDAP 服务器

也许解决这些问题已经有助于解决根本问题。否则为 RESTAuthenticationEntryPoint 添加代码并记录到问题中。

【讨论】:

  • 我没有自定义 RESTAuthenticationEntryPoint。这些已被注释掉并从上面的代码中删除。
  • Spring(Security) 没有名为“RESTAuthenticationEntryPoint”的类,它必须是你引入的自定义类。
  • 此外,Spring Security 没有身份验证机制,您可以将带有 JSON 格式凭据的 POST 请求发送到任何应该受到保护的 URL。如果这应该起作用,那一定是你带来的东西。
猜你喜欢
  • 2017-04-12
  • 2022-01-20
  • 2020-11-13
  • 2020-05-22
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2011-01-12
  • 2020-09-08
相关资源
最近更新 更多