需求说明
局方所有人的电脑都在一个域中管理,员工通过域账号和密码登录他的计算机之后,在登录应用系统之后不再需要做登入操作,直接进入系统;
实现方法
通过查询资料,JCIFS可以实现域单点登入,实现原理可以查看这个链接:
http://www.cnblogs.com/adylee/articles/975213.html
实现方法也比较简单,步骤如下:
1.jcifs官网http://jcifs.samba.org/下载最新jar包
2.配置过滤器
<filter>
<filter-name>NtlmHttpFilter</filter-name>
<filter-class>jcifs.http.NtlmHttpFilter</filter-class>
<init-param>
<param-name>jcifs.http.domainController</param-name>
<param-value>10.45.40.222</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>NtlmHttpFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
由于我只要通过JCIFS获取客户端的系统用户,并没有通过JCIFS登入AD验证用户(用户登入的时候已经验证了),所有这里配的参数就一个。
3.修改过滤器NtlmHttpFilter的代码,去掉AD登入
protected NtlmPasswordAuthentication negotiate(HttpServletRequest req, HttpServletResponse resp,
boolean skipAuthentication) throws IOException, ServletException {
UniAddress dc;
String msg;
NtlmPasswordAuthentication ntlm = null;
msg = req.getHeader("Authorization");
boolean offerBasic = enableBasic && (insecureBasic || req.isSecure());
logger.info("NtlmHttpFilter negotiate msg:" + msg);
logger.info("NtlmHttpFilter negotiate offerBasic:" + offerBasic);
if (msg != null && (msg.startsWith("NTLM ") || (offerBasic && msg.startsWith("Basic ")))) {
if (msg.startsWith("NTLM ")) {
HttpSession ssn = req.getSession();
byte[] challenge;
logger.info("NtlmHttpFilter negotiate loadBalance:" + loadBalance);
if (loadBalance) {
NtlmChallenge chal = (NtlmChallenge) ssn.getAttribute("NtlmHttpChal");
if (chal == null) {
chal = SmbSession.getChallengeForDomain();
ssn.setAttribute("NtlmHttpChal", chal);
}
dc = chal.dc;
challenge = chal.challenge;
} else {
dc = UniAddress.getByName(domainController, true);
challenge = SmbSession.getChallenge(dc);
}
if ((ntlm = NtlmSsp.authenticate(req, resp, challenge)) == null) {
return null;
}
/* negotiation complete, remove the challenge object */
ssn.removeAttribute("NtlmHttpChal");
} else {
String auth = new String(Base64.decode(msg.substring(6)), "US-ASCII");
int index = auth.indexOf(':');
String user = (index != -1) ? auth.substring(0, index) : auth;
String password = (index != -1) ? auth.substring(index + 1) : "";
index = user.indexOf('\\');
if (index == -1)
index = user.indexOf('/');
String domain = (index != -1) ? user.substring(0, index) : defaultDomain;
user = (index != -1) ? user.substring(index + 1) : user;
ntlm = new NtlmPasswordAuthentication(domain, user, password);
dc = UniAddress.getByName(domainController, true);
}
/*
* try { logger.info(
* "NtlmHttpFilter SmbSession logon....ntlm.getName():"
* +ntlm==null?null:ntlm.getName()); SmbSession.logon( dc, ntlm );
*
* if( log.level > 2 ) { logger.info( "NtlmHttpFilter: " + ntlm +
* " successfully authenticated against " + dc ); } logger.info(
* "NtlmHttpFilter SmbSession logon successfully...."); }
* catch(SmbException sae ) { logger.info(
* "NtlmHttpFilter SmbSession logon error....msg:"+ntlm.getName()+
* " auth error:"+sae.getMessage());
*
* if( log.level > 1 ) { logger.info( "NtlmHttpFilter: " +
* ntlm.getName() + ": 0x" + jcifs.util.Hexdump.toHexString(
* sae.getNtStatus(), 8 ) + ": " + sae ); } if( sae.getNtStatus() ==
* SmbAuthException.NT_STATUS_ACCESS_VIOLATION ) { Server challenge
* no longer valid for externally supplied password hashes.
*
* HttpSession ssn = req.getSession(false); if (ssn != null) {
* ssn.removeAttribute( "NtlmHttpAuth" ); } } resp.setHeader(
* "WWW-Authenticate", "NTLM" ); if (offerBasic) { resp.addHeader(
* "WWW-Authenticate", "Basic realm=\"" + realm + "\""); }
* if(showDlg){ resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED
* ); resp.setContentLength(0); Marcel Feb-15-2005
* resp.flushBuffer(); }
*
*
* return null; } req.getSession().setAttribute( "NtlmHttpAuth",
* ntlm );
*/
} else {
if (!skipAuthentication) {
HttpSession ssn1 = req.getSession(false);
if (ssn1 == null || (ntlm = (NtlmPasswordAuthentication) ssn1.getAttribute("NtlmHttpAuth")) == null) {
resp.setHeader("WWW-Authenticate", "NTLM");
if (offerBasic) {
resp.addHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
}
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.setContentLength(0);
resp.flushBuffer();
return null;
}
}
}
return ntlm;
}
完成以上几步,就可以通过request.getUserPrincipal();获取客户端系统用户名了。
在项目中,把过滤器整合进去,虽然实现了需求,但是遇到个问题。
加了这个过滤器后,之后的所有请求都会发多次,查看附件图片
这个也能理解,因为JCIFS实现的原理就是在请求的头文件加Authorization。这样每次请求都需要验证一次。那么问题就来了,由于框架是通过request.getInputStream获取请求参数再做分析,而http发送的验证请求body是为空,导致后面的程序报错。就不得不再后面的解析中判断一下输入流是否为空,再做处理。
我就想能不能怎么控制HTTP只在发登入请求的时候才发验证请求,其他的请求就不要用了。
想办法删掉headers中的Authorization参数,查找资料只有
response.setHeader("WWW-Authenticate","NTLM"");却没有移除这个参数的方法。。
求大神们指点一二
- 描述: 每个请求发多次
- 大小: 96.7 KB
分享到:
相关推荐
jcifs.jar支持域单点登录。只是jcifs.jar包。之前项目用过还不错。
jcifs库可以处理这些复杂的认证流程,使Java应用能够与Windows域控制器进行交互,实现用户的统一认证。 2. **会话管理**:jcifs提供会话管理功能,能够在用户成功登录后保存其凭证,以便在后续请求中复用,从而实现...
总的来说,通过Java和NTLM协议实现AD域的单点登录,能够提供安全、便捷的用户体验,同时减轻了IT部门的管理负担。在实际开发过程中,需要对AD域架构有深入理解,熟悉Java编程以及相关的身份验证机制。提供的资源,...
5. **问题与解决方案**:可能会讨论在实际应用中可能遇到的问题,如跨域认证、代理服务器支持等,以及对应的解决策略。 在给定的压缩包文件中,我们看到有以下几个文件: - `index.jsp`:这通常是Web应用的首页,...
CAS是实现单点登录的重要组件,简化了用户认证流程。当遇到Maven下载问题时,可以考虑手动添加依赖到项目。而Samba则是在操作系统层面上实现SMB协议,使得非Windows系统也能与Windows网络进行交互。
6. **单点登录(Single Sign-On, SSO)原理**:虽然标签中提到了“单点登录代码”,但jcifs本身并不直接提供SSO功能。不过,jcifs可以作为实现SSO的一个组件,因为它能处理网络认证。如果你打算开发SSO系统,理解...
需要注意的是,jcifs库在处理大文件时可能会遇到问题,如网络中断、超时或内存溢出等。为解决这些问题,可以考虑以下策略: - **分块读写**:将大文件分割成小块进行读写,减少一次性处理的数据量。 - **异常处理**...
4. **域环境支持**:在Windows域环境中,jcifs能够处理域用户和组的权限,使得在域内的文件操作更加顺畅。 5. **异步操作**:jcifs库提供了异步I/O操作,可以在后台线程中执行文件操作,避免阻塞主线程,提高程序的...
jcifs-ext-0.9.4.jar便是这样一个关键的拓展包,它为Java应用程序提供了与Windows网络身份验证交互的能力,特别是在实施单点登录(Single Sign-On, SSO)系统如CAS(Central Authentication Service)时。...
Java共享文件下载依赖包jcifs-1.3.3.jar是一个关键组件,它主要用于Java程序在不同操作系统之间实现网络文件共享。这个包是基于Java的CIFS(Common Internet File System)客户端实现,允许Java应用程序与遵循SMB...
**jcifs-1.3.15.jar** 是一个Java库,主要用于在Java应用程序中实现对SMB(Server Message Block)协议的支持。SMB是一种广泛使用的网络文件共享协议,尤其在Windows环境中,它允许不同设备在局域网(LAN)内共享...
jcifs-1.3.18.jar包,SSO单点登录
<param-name>jcifs.smb.client.domain 域名 <param-name>jcifs.netbios.wins 域服务器的IP <param-name>jcifs.util.loglevel <param-value>0 <param-name>jcifs.smb....
jcifs-1.3.19.jar 包,用于SMB协议 ,以实现远程读取文件。jcifs-1.3.19.jar 包,用于SMB协议 ,以实现远程读取文件。
总的来说,jcifs为Java开发者提供了一种便捷的方式来处理CIFS协议的文件系统操作,使得在跨平台的环境中实现文件共享变得简单。通过正确理解和运用jcifs库,我们可以高效地完成远程文件系统的管理工作。
jcifs-1.3.14.jar是jcifs库的一个版本,提供了对CIFS协议的支持,使得Java开发者可以实现跨平台的文件共享和传输。 CIFS(Common Internet File System)是一种广泛使用的文件共享协议,尤其在Windows环境中。它...
通过jcifs实现java访问网络共享文件 jcifs 是 cifs(common internet file system) java的实现 smb (service message block) to be cifs jcifs 是一个开源项目 可从http://jcifs.samba.org/下载 SmbFileInputStream...
- 由于jcifs是基于TCP/IP的,网络不稳定可能会导致连接问题,需处理好异常情况。 - 对于性能敏感的应用,需要注意jcifs的性能瓶颈,如文件读写速度、网络延迟等。 jcifs API 为Java开发者提供了一个强大而灵活的...