Java 单点登录在Spring web app中不起作用
我将我的web应用程序配置为通过Active Directory repo进行身份验证,它工作正常,但我始终需要在登录表单中插入凭据 应用程序客户端将是连接到公司网络的Windows计算机,所有这些计算机都在同一个域中 我需要将我的web应用配置为自动验证在Windows中已验证的用户 我将此配置用于Spring Security:Java 单点登录在Spring web app中不起作用,java,spring,authentication,spring-security,active-directory,Java,Spring,Authentication,Spring Security,Active Directory,我将我的web应用程序配置为通过Active Directory repo进行身份验证,它工作正常,但我始终需要在登录表单中插入凭据 应用程序客户端将是连接到公司网络的Windows计算机,所有这些计算机都在同一个域中 我需要将我的web应用配置为自动验证在Windows中已验证的用户 我将此配置用于Spring Security: <security:authentication-manager alias="authenticationManager"> <secu
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="userDetailsService">
<security:password-encoder hash="plaintext" />
</security:authentication-provider> <!-- for DB authentication -->
<security:authentication-provider
ref="adAuthenticationProvider" />
</security:authentication-manager>
<bean id="adAuthenticationProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg name="domain" value="mydomain.it" />
<constructor-arg name="url" value="ldap://domaincontroller.mydomain.it/" />
</bean>
注意我还需要一个辅助身份验证提供商来提供DB身份验证
我还在IE(v 9)中设置了以下选项,该选项应启用自动登录:
但它不起作用。。。那么我的配置有什么问题
注意#2我使用的是SpringV3.2.9和SpringSecurityV3.2.3您配置的是LDAP身份验证如果要进行自动身份验证,必须使用Kerberos/SPNEGO Spring有一个用于Kerberos/SPNEGO身份验证检查的模块,该模块解释了Kerberos/SPNEGO如何工作以及如何配置Spring安全性 您还必须在IE中启用“Windows集成身份验证”,如下所示
正确的方法是使用Kerberos/SPNEGO。但是,服务器必须是Windows域上的受信任节点。如果您的服务器是Windows计算机,那么这应该足够简单。然而,如果它是一台“NIX/Linux机器”,那么它可以是一台真正的PITA 这包括在Active Directory中使用SPN(服务主体名称)进行设置,以及在服务器上安装一大堆东西,以便与a/D集成,并对用户进行身份验证 如果您(或您友好的Windows基础架构团队成员)对所有这些都感到满意,那么就去做吧!但是,如果您不熟悉它,我应该警告您,当它不起作用时,诊断问题就是地狱 但是,有一个快速且肮脏的选项,它不涉及对网络上的服务器的任何信任。事实上,整个过程都可以在你的Spring应用程序中完成。这是一个不太安全,但它的工作NTLM。设置起来很容易 首先,如果没有会话,您需要一个Servlet过滤器来拦截请求并执行握手:
import java.io.IOException;
导入org.apache.commons.codec.binary.Base64;
导入javax.servlet.Filter;
导入javax.servlet.FilterChain;
导入javax.servlet.FilterConfig;
导入javax.servlet.ServletException;
导入javax.servlet.ServletRequest;
导入javax.servlet.ServletResponse;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.context.annotation.Profile;
导入org.springframework.stereotype.Component;
/**
*设计用于通过NTLM SSO获取用户名的简单身份验证过滤器。
*请参阅有关预认证过滤器的Spring文档,了解如何使用它。
*
*
*
*
*/
@组件(“ntlmFilter”)
公共类NtlmFilter实现过滤器{
私有静态记录器log=LoggerFactory.getLogger(NtlmFilter.class);
公共静态最终字符串USERNAME\u KEY=“SM\u USER”;
公共NtlmFilter(){
log.info(“初始化NTLM过滤器”);
}
@凌驾
public void init(FilterConfig FilterConfig)抛出ServletException{
//没有初始化任务。
}
@凌驾
公共空间销毁(){
//没有销毁任务。
}
/**
*
*/
@凌驾
公共无效doFilter(ServletRequest-req、ServletResponse-res、FilterChain链)
抛出IOException、ServletException{
HttpServletRequest请求=(HttpServletRequest)请求;
HttpServletResponse=(HttpServletResponse)res;
如果(未验证(请求)){
debug(“会话已通过身份验证。继续向下筛选链”);
setRequestHeaders(请求);
继续(请求、回复、链);
}否则{
调试(“会话尚未验证。正在尝试登录…”);
登录(请求、响应、链);
}
}
私有无效继续(ServletRequest-req、ServletResponse-res、FilterChain链)
抛出IOException、ServletException{
试一试{
链式过滤器(要求、恢复);
}捕获(IOE异常){
错误(“IOException processing NtlmAuthFilter Servlet filter.”,e);
投掷e;
}捕获(ServletException e){
错误(“ServletException处理NtlmAuthFilter Servlet筛选器”,e);
投掷e;
}
}
/**
*如果用户名已存储在会话中,则该用户已被删除
*由应用程序验证。
*/
私有布尔值已验证(HttpServletRequest请求){
if(req.getSession().getAttribute(用户名\密钥)!=null){
返回true;
}否则{
返回false;
}
}
公共无效登录(HttpServletRequest-req、HttpServletResponse-res、FilterChain-chain)引发ServletException、IOException{
字符串username=null;
字符串auth=req.getHeader(“授权”);
if(auth==null){
//第一阶段。返回NTLM质询标头。
res.setHeader(“WWW-Authenticate”、“NTLM”);
res.setStatus(HttpServletResponse.SC_未经授权);
res.setContentLength(0);
res.flushBuffer();
返回;
}else if(授权开始使用(“NTLM”)){
字节[]msg=Base64.decodeBase64(验证子字符串(5));
int off=0,长度,偏移量;
如果(消息[8]==1){
//登录详细信息无效。请拒绝。
字节z=0;
字节[]msg1={(字节)'N',(字节)'T',(字节)'L',
(字节)‘M’,(字节)‘S’,(字节
@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@Profile("secure")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired(required = true)
@Qualifier("ntlmFilter")
private Filter ntlmFilter;
@Autowired(required = true)
@Qualifier("headerAuthFilter")
private Filter headerAuthFilter;
// ...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(ntlmFilter, RequestHeaderAuthenticationFilter.class)
.anonymous().disable()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(http403ForbiddenEntryPoint());
}
@Bean(name = "headerAuthFilter")
public Filter headerAuthFilter(AuthenticationManager authenticationManager) {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
filter.setPrincipalRequestHeader("SM_USER");
filter.setAuthenticationManager(authenticationManager);
filter.setExceptionIfHeaderMissing(false);
return filter;
}
// ...
}