Problems encountered in implementing domain single sign-on with JCIFS

It should be noted that
all the computers of the bureau are managed in a domain. After the employee logs in to his computer through the domain account and password, he no longer needs to do the login operation after logging in to the application system, and directly enters the system; the

realization method
is to query the data, JCIFS Domain single sign-on can be realized, and the implementation principle can be viewed at this link:

http://www.cnblogs.com/adylee/articles/975213.html The

implementation method is also relatively simple, the steps are as follows:
1.jcifs official website http://jcifs. samba.org/Download the latest jar package
2. Configure filters

      <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>



Since I only need to obtain the system user of the client through JCIFS, and I did not log in to AD to verify the user through JCIFS (the user has been verified when logging in), all the parameters here are only one.
3. Modify the code of the filter NtlmHttpFilter to remove AD login
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;
	}

After completing the above steps, you can obtain the user name of the client system through request.getUserPrincipal();.

In the project, the filter is integrated, although the requirements are realized, but a problem is encountered.
After adding this filter, all subsequent requests will be sent multiple times, and

it , because the principle of JCIFS implementation is to add Authorization to the request header file. This way each request needs to be authenticated once. Then the problem comes, because the framework obtains the request parameters through request.getInputStream for analysis, and the verification request body sent by http is empty, resulting in an error in the subsequent program. You have to judge whether the input stream is empty in the subsequent analysis, and then process it.

I wondered if I could control how HTTP would only send an authentication request when sending a login request, and not use it for other requests.

Try to delete the Authorization parameter in the headers, and find the data only
response.setHeader("WWW-Authenticate","NTLM""); but there is no way to remove this parameter. .
Ask the gods for guidance

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326440920&siteId=291194637