jcifs包实现域认证的单点登录带来了个奇怪的问题



  先简述一下系统使用的技术,框架是struts1.2,action继承LookupDispatchAction,页面的验证使用validation,应用服务器为jboss4.2
  问题描述:
  在web.xml配置文件中配置了实现域登录的Servlet后出现如下问题:
  点击系统的“增加”按钮弹出的页面中的“保存”按钮无法调用action中对应的方法;
  “修改”按钮弹出页面的“保存”则出现如下错误
  WARN [RequestProcessor] Unhandled Exception thrown: classjavax.servlet.ServletException
  INFO [[/]] Request[/doc/docmanagedetailaction] does not contain handlerparameter named 'act'. This may be caused by whitespace in the label text.

jsp页面中的“保存”按钮代码
<html:submit styleClass="button" property="act"onclick="return chkpagecount();">
  <bean:message key="button.save" />
</html:submit>


实现域登录的Java文件(http://www.jcifs.com/可以下载相应的jar包)
/**
 * 本java文件来自于jcifs.http.NtlmHttpFilter.java
*/

@SuppressWarnings({"serial","unused"})
public class ADServlet extends HttpServlet {

  private static LogStream log = LogStream.getInstance();

  private String defaultDomain;

  private String domainController;

  private boolean loadBalance;

  private boolean enableBasic;

  private boolean insecureBasic;

  private String realm;

  private Map map;

  /**

  * Initialize this servlet.

  *

  * @exception ServletException

  * if we cannot configure ourselves correctly

  */

  public void init(ServletConfig config) throws ServletException {

  map=new HashMap();

  Config.setProperty("jcifs.smb.client.soTimeout","1800000");

  Config.setProperty("jcifs.netbios.cachePolicy","1200");

  Config.setProperty("jcifs.smb.lmCompatibility","0");

  Config.setProperty("jcifs.smb.client.useExtendedSecurity","false");

  Enumeration e = config.getInitParameterNames();

  do {

  if (!e.hasMoreElements()) {

  break;

  }

  String name = (String) e.nextElement();

  if (name.startsWith("jcifs.")) {

  Config.setProperty(name, config.getInitParameter(name));

  }

  } while (true);

  defaultDomain = Config.getProperty("jcifs.smb.client.domain");

  domainController =Config.getProperty("jcifs.http.domainController");

  if (domainController == null) {

  domainController = defaultDomain;

  loadBalance = Config.getBoolean("jcifs.http.loadBalance",true);

  }

  enableBasic =Boolean.valueOf(Config.getProperty("jcifs.http.enableBasic")).booleanValue();

  insecureBasic =Boolean.valueOf(Config.getProperty("jcifs.http.insecureBasic")).booleanValue();

  realm = Config.getProperty("jcifs.http.basicRealm");

  if (realm == null) {

  realm = "jCIFS";

  }

  int level;

  if ((level = Config.getInt("jcifs.util.loglevel", -1)) != -1){

  LogStream.setLevel(level);

  }

  LogStream _tmp = log;

  if (LogStream.level > 2) {

  try {

  Config.store(log, "JCIFS PROPERTIES");

  } catch (IOException ioe) {

 

  }

  }

  }

 

  public void doGet(HttpServletRequest request, HttpServletResponseresponse)

  throws IOException, ServletException {

  NtlmPasswordAuthentication ntlm;

  try{

  if ((ntlm = negotiate(request, response, false)) == null) {

   

  return;

  } else {

  String uuname=(String)map.get("adremoteuser");

  System.out.println("\t\t域登陆用户名:"+uuname);

 uuname=uuname.substring(uuname.indexOf("\\")+1,uuname.length());response.sendRedirect(request.getContextPath()+"/loginaction.do?act=login&companycode=test&username="+uuname+"&password=***");

  return;

  }

  }catch (Exception e) {

  e.printStackTrace();

  }

  }

 

  public void doPost(HttpServletRequest request, HttpServletResponseresponse)

  throws IOException, ServletException {

  doGet(request, response);

  }

  public void destroy() {

  map=null;

  }

   

  protected NtlmPasswordAuthentication negotiate(HttpServletRequest req,HttpServletResponse resp,

boolean skipAuthentication) throws IOException, ServletException {

  NtlmPasswordAuthentication ntlm = null;

  String msg = req.getHeader("Authorization");

  boolean offerBasic = enableBasic && (insecureBasic ||req.isSecure());

  if (msg != null && (msg.startsWith("NTLM ") ||offerBasic && msg.startsWith("Basic "))) {

  UniAddress dc;

  if (msg.startsWith("NTLM ")) {

  HttpSession ssn = req.getSession();

  byte challenge[];

  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;

  }

  ssn.removeAttribute("NtlmHttpChal");

  } else {

  String auth = new String(Base64.decode(msg.substring(6)),"US-ASCII");

  int index = auth.indexOf(':');

  String user = index == -1 ? auth : auth.substring(0, index);

  String password = index == -1 ? "" : auth.substring(index +1);

  index = user.indexOf('\\');

  if (index == -1) {

  index = user.indexOf('/');

  }

  String domain = index == -1 ? defaultDomain : user.substring(0,index);

  user = index == -1 ? user : user.substring(index + 1);

  ntlm = new NtlmPasswordAuthentication(domain, user, password);

  dc = UniAddress.getByName(domainController, true);

  }

  map.put("adremoteuser", ntlm.getName());

  try {

  SmbSession.logon(dc, ntlm);

  LogStream _tmp = log;

  if (LogStream.level > 2) {

  log.println("NtlmHttpFilter: " + ntlm + " successfullyauthenticated against " + dc);

  }

  } catch (SmbAuthException sae) {

  LogStream _tmp1 = log;

  if (LogStream.level > 1) {

  log.println("NtlmHttpFilter: " + ntlm.getName() + ":0x" + Hexdump.toHexString(sae.getNtStatus(), 8) + ": " + sae);

  }

  SmbAuthException _tmp2 = sae;

  if (sae.getNtStatus() == 0xc0000005) {

  HttpSession ssn = req.getSession(false);

  if (ssn != null) {

  ssn.removeAttribute("NtlmHttpAuth");

  }

  }

  resp.setHeader("WWW-Authenticate", "NTLM");

  if (offerBasic) {

  resp.addHeader("WWW-Authenticate", "Basicrealm=\"" + realm + "\"");

  }

  resp.setStatus(401);

  resp.setContentLength(0);

  resp.flushBuffer();

  return null;

  }

  req.getSession().setAttribute("NtlmHttpAuth", ntlm);

  } else if (!skipAuthentication) {

  HttpSession ssn = req.getSession(false);

  if (ssn == null || (ntlm = (NtlmPasswordAuthentication)ssn.getAttribute("NtlmHttpAuth")) == null) {

  resp.setHeader("WWW-Authenticate", "NTLM");

  if (offerBasic) {

  resp.addHeader("WWW-Authenticate", "Basicrealm=\"" + realm + "\"");

  }

  resp.setStatus(401);

  resp.setContentLength(0);

  resp.flushBuffer();

  return null;

  }

  }

  return ntlm;

  }

}

Web.Xml中配置
<servlet>
  <servlet-name>myadservlet</servlet-name>
  <servlet-class>com. company.test.ADServlet</servlet-class>
  <init-param>
  <param-name>jcifs.http.domainController</param-name>
  <param-value>172.16.2.101</param-value>
  </init-param>
  <init-param>
  <param-name>jcifs.netbios.wins</param-name>
  <param-value>172.16.2.101,172.16.2.105</param-value>
  </init-param>
  <init-param>
  <param-name>jcifs.smb.client.domain</param-name>
  <param-value>dns. company.net.cn</param-value>
  </init-param>
  <init-param>
  <param-name>jcifs.smb.client.soTimeout</param-name>
  <param-value>18000</param-value>
  </init-param>
  <init-param>
  <param-name>jcifs.netbios.cachePolicy</param-name>
  <param-value>1200</param-value>
  </init-param>
  <init-param>
  <param-name>jcifs.util.loglevel</param-name>
  <param-value>0</param-value>
  </init-param>
  <load-on-startup>3</load-on-startup>
  </servlet>
  <servlet-mapping>

若要解决此问题,从客户端,使用注册表编辑器 (Regedt32.exe) 将值添加到以下注册表项:
HKEY_CURRENT_USER/软件/microsoft/windows/CurrentVersion/internet设置 / 
注意上面的注册表项是一个路径,它经过了折行以提高可读性。

添加以下注册表值:
值名称: DisableNTLMPreAuth
数据类型: REG_DWORD
值: 1 
除了注册表项还需要关闭 Internet Explorer 中 启用集成 Windows 身份验证。 若要这样做,请按照下列步骤操作: 
启动 Internet Explorer。
单击 工具,请单击 Internet 选项,然后单击 高级 选项卡。
在 安全,下单击以取消选择 启用集成 Windows 身份验证 (需要重启动),然后单击 应用。
关闭 Internet Explorer。
若要解决此问题,从服务器端,配置网站以使用下列身份验证方法之一:
若要允许匿名访问仅网站进行配置。
配置为允许匿名访问和 NLTM 身份验证 (集成 Windows 身份验证) 的网站

廖世勇
原文地址:https://www.cnblogs.com/liaoshiyong/p/3150858.html