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

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

[b]实现方法[/b]
通过查询资料,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");却没有移除这个参数的方法。。
求大神们指点一二
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值