`

JCIFS实现域单点登入遇到的问题

阅读更多
需求说明
局方所有人的电脑都在一个域中管理,员工通过域账号和密码登录他的计算机之后,在登录应用系统之后不再需要做登入操作,直接进入系统;

实现方法
通过查询资料,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&quot");却没有移除这个参数的方法。。
求大神们指点一二
  • 描述: 每个请求发多次
  • 大小: 96.7 KB
分享到:
评论

相关推荐

    jcifs.jar支持java域单点登录

    jcifs.jar支持域单点登录。只是jcifs.jar包。之前项目用过还不错。

    jcifs实现集成登录

    jcifs库可以处理这些复杂的认证流程,使Java应用能够与Windows域控制器进行交互,实现用户的统一认证。 2. **会话管理**:jcifs提供会话管理功能,能够在用户成功登录后保存其凭证,以便在后续请求中复用,从而实现...

    AD域单点登陆NTLM

    总的来说,通过Java和NTLM协议实现AD域的单点登录,能够提供安全、便捷的用户体验,同时减轻了IT部门的管理负担。在实际开发过程中,需要对AD域架构有深入理解,熟悉Java编程以及相关的身份验证机制。提供的资源,...

    域登陆(通过jcifs.http.NtlmHttpFilter实现)

    5. **问题与解决方案**:可能会讨论在实际应用中可能遇到的问题,如跨域认证、代理服务器支持等,以及对应的解决策略。 在给定的压缩包文件中,我们看到有以下几个文件: - `index.jsp`:这通常是Web应用的首页,...

    jcifs-ext-0.9.4.jar/jcifs-1.3.3.jar

    CAS是实现单点登录的重要组件,简化了用户认证流程。当遇到Maven下载问题时,可以考虑手动添加依赖到项目。而Samba则是在操作系统层面上实现SMB协议,使得非Windows系统也能与Windows网络进行交互。

    jcifs包 源代码

    6. **单点登录(Single Sign-On, SSO)原理**:虽然标签中提到了“单点登录代码”,但jcifs本身并不直接提供SSO功能。不过,jcifs可以作为实现SSO的一个组件,因为它能处理网络认证。如果你打算开发SSO系统,理解...

    利用jcifs-1.3.15.jar实现共享文件上传下载

    需要注意的是,jcifs库在处理大文件时可能会遇到问题,如网络中断、超时或内存溢出等。为解决这些问题,可以考虑以下策略: - **分块读写**:将大文件分割成小块进行读写,减少一次性处理的数据量。 - **异常处理**...

    jcifs-1.3.16.jar及源码

    4. **域环境支持**:在Windows域环境中,jcifs能够处理域用户和组的权限,使得在域内的文件操作更加顺畅。 5. **异步操作**:jcifs库提供了异步I/O操作,可以在后台线程中执行文件操作,避免阻塞主线程,提高程序的...

    jcifs-ext-0.9.4.jar

    jcifs-ext-0.9.4.jar便是这样一个关键的拓展包,它为Java应用程序提供了与Windows网络身份验证交互的能力,特别是在实施单点登录(Single Sign-On, SSO)系统如CAS(Central Authentication Service)时。...

    java共享文件下载依赖包jcifs-1.3.3.jar

    Java共享文件下载依赖包jcifs-1.3.3.jar是一个关键组件,它主要用于Java程序在不同操作系统之间实现网络文件共享。这个包是基于Java的CIFS(Common Internet File System)客户端实现,允许Java应用程序与遵循SMB...

    jcifs-1.3.15.jar

    **jcifs-1.3.15.jar** 是一个Java库,主要用于在Java应用程序中实现对SMB(Server Message Block)协议的支持。SMB是一种广泛使用的网络文件共享协议,尤其在Windows环境中,它允许不同设备在局域网(LAN)内共享...

    jcifs-1.3.18.jar

    jcifs-1.3.18.jar包,SSO单点登录

    jcifs-1.3.17.jar

    &lt;param-name&gt;jcifs.smb.client.domain 域名 &lt;param-name&gt;jcifs.netbios.wins 域服务器的IP &lt;param-name&gt;jcifs.util.loglevel &lt;param-value&gt;0 &lt;param-name&gt;jcifs.smb....

    jcifs-1.3.19.jar

    jcifs-1.3.19.jar 包,用于SMB协议 ,以实现远程读取文件。jcifs-1.3.19.jar 包,用于SMB协议 ,以实现远程读取文件。

    Jcifs创建远程文件夹的例子

    总的来说,jcifs为Java开发者提供了一种便捷的方式来处理CIFS协议的文件系统操作,使得在跨平台的环境中实现文件共享变得简单。通过正确理解和运用jcifs库,我们可以高效地完成远程文件系统的管理工作。

    共享文件传输-Jcifs

    jcifs-1.3.14.jar是jcifs库的一个版本,提供了对CIFS协议的支持,使得Java开发者可以实现跨平台的文件共享和传输。 CIFS(Common Internet File System)是一种广泛使用的文件共享协议,尤其在Windows环境中。它...

    jcifs-1.3.12.zip

    通过jcifs实现java访问网络共享文件 jcifs 是 cifs(common internet file system) java的实现 smb (service message block) to be cifs jcifs 是一个开源项目 可从http://jcifs.samba.org/下载 SmbFileInputStream...

    jcifs API开发文档、jar包等

    - 由于jcifs是基于TCP/IP的,网络不稳定可能会导致连接问题,需处理好异常情况。 - 对于性能敏感的应用,需要注意jcifs的性能瓶颈,如文件读写速度、网络延迟等。 jcifs API 为Java开发者提供了一个强大而灵活的...

Global site tag (gtag.js) - Google Analytics