`
juforg
  • 浏览: 44732 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JCIFS 自定义 域登录 SSO

阅读更多

参考:http://jusescn.iteye.com/blog/757475http://www.iteye.com/problems/61029

以及其他网上资料

 

1.概念

单点登录:http://baike.baidu.com/view/993620.htmhttp://baike.baidu.com/view/190743.htm

JCIFS:官网 http://jcifs.samba.org/, 域验证,共享文件操作

 

2. IE 设置



  无论在不在域中都会进行一次自动登录,不在域中则登录报错,catch住exception 后跳转到普通登录页面

3.web.xml

	<filter>
		<filter-name>checkLogin</filter-name>
		<filter-class>com.XXX.xxx.filter.CheckLoginFilter</filter-class>
		<init-param>
            <param-name>excludeUrl</param-name>
            <param-value>login.jsp,login.do,loginService.do,change.do,upload.jsp</param-value>
        </init-param>
		<init-param>
            <param-name>loginPage</param-name>
            <param-value>login.jsp</param-value>
        </init-param>
	</filter>

 

3.Filter

public class CheckLoginFilter implements Filter {
	private List<String> excludePages = new ArrayList<String>(0);
	private String LOGIN_PAGE = "";
	private final Logger logger = TraceLoggerFactory.getLogger(this.getClass());
	private LoginService loginService = new LoginService();
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		HttpServletResponse httpServletResponse = (HttpServletResponse)response;
		String servletPath = httpServletRequest.getServletPath();
		NtlmPasswordAuthentication ntlm = null;
		String[] paths = servletPath.split("/");
		
		if(!excludePages.contains(paths[paths.length-1])){
			Object userInfoObj = httpServletRequest.getSession().getAttribute("user");
			String userName = request.getParameter("userName");
			if(userInfoObj == null){
				boolean loginFlag = false;
				try {
				//读取域配置 ,将配置放入配置文件中 读取
				Config.setProperty( "jcifs.http.domainController","192.168.1.0"+","+ "192.168.1.1");
				Config.setProperty( "jcifs.smb.client.domain", "testDomain" );
				//进行域登录验证
				loginFlag = (ntlm = loginService.negotiate( httpServletRequest, httpServletResponse, false )) !=null;
				} catch (Exception e) {
					//e.printStackTrace();
				}
				if (loginFlag) {
					logger.info("域账户:" + ntlm.getUsername()+"已登录!");
					DataObject[] userAccounts = userManager.queryByDomainAndName(ntlm.getUsername(),null);
					if(userAccounts != null && userAccounts.length > 0){
						//如果请求中包含用户名,则根据此用户名查找对应域账户是否已登录
						if (!StringUtil.isBlank(userName)) {
							for (DataObject object : userAccounts) {
								if (userName.equals(object.getString("account"))) {
									loginService.setUser2SessionByAccount(httpServletRequest, object);
								}
							}
						}else{
							if(userAccounts.length == 1){
								loginService.setUser2SessionByAccount(httpServletRequest, userAccounts[0]);
							}else if(userAccounts.length > 1){
								//进入多账户选择页面
								request.setAttribute("userInfos", userAccounts);
								request.setAttribute("prePath", httpServletRequest.getContextPath()+ servletPath);
								request.getRequestDispatcher("switch_user.jsp").forward(request,response);
								return;
							}
						}
						if(servletPath.endsWith("/login.jsp") ||servletPath.endsWith("index.jsp")){
							httpServletResponse.sendRedirect("epf_index.jsp");
						}else{
							request.getRequestDispatcher(servletPath).forward(request,response);
						}
						return;
					}
				}
				DataObject userInfo1 = (DataObject)httpServletRequest.getSession().getAttribute("user");
				if(userInfo1 == null ){
					httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/"+LOGIN_PAGE);
					return;
				}
			} 
		}
		 chain.doFilter( new NtlmHttpServletRequest( httpServletRequest, ntlm ), response );
	}
	
	public void init(FilterConfig config) throws ServletException {
		LOGIN_PAGE = config.getInitParameter("loginPage");
		String excludePage = config.getInitParameter("excludeUrl");
		if(excludePage != null && !"".equals(excludePage)){
			String[] excludePages =  excludePage.split(",");
			this.excludePages = Arrays.asList(excludePages);
		}
		//初始化 JCIFS的配置信息
		loginService.initJcifsConfig();
	}
	
	/**从源码中弄过来的 不知道有啥用
	*/
    class NtlmHttpServletRequest extends HttpServletRequestWrapper {

        Principal principal;

        NtlmHttpServletRequest( HttpServletRequest req, Principal principal ) {
            super( req );
            this.principal = principal;
        }
        public String getRemoteUser() {
            return principal.getName();
        }
        public Principal getUserPrincipal() {
            return principal;
        }
        public String getAuthType() {
            return "NTLM";
        }
    }
    
}

 

public class LoginService {
	
	TraceLogger logger = new TraceLogger(LoginService.class);
	UserManager userManager = new UserManager();
	private static LogStream log = LogStream.getInstance();
	
	private String defaultDomain;
    private String domainController;
    private boolean loadBalance;
    private boolean enableBasic;
    private boolean insecureBasic;
    private String realm;
    
	
	public boolean setUser2SessionByAccount(HttpServletRequest request,DataObject account){
		String accountStatus = account.getString("accountStatus");
		if(accountStatus.equals("Y")){
			DataObject user = getUserInfoByUserId(account.getString("accountId"));
			user.setString("loginIp", request.getRemoteAddr());
			System.out.println("loginIp:"+request.getRemoteAddr());
			request.getSession().setAttribute("user", user);
			request.getSession().setAttribute(SynchroToken.TOKEN_NAME, SynchroToken.generateToken());
			return true;
		}
		return false;
	}
	
	public boolean setUser2SessionByUserName(HttpServletRequest request, String userName){
		DataObject account = userManager.queryByAccount(userName);
		return setUser2SessionByAccount(request, account);
	}
	
	public void initJcifsConfig(){
        int level;

//        Config.setProperty( "jcifs.http.domainController", "192.168.0.14" );
//        Config.setProperty( "jcifs.smb.client.domain", "epfnet" );
//        Config.setProperty( "jcifs.smb.client.username", "administrator" );
//        Config.setProperty( "jcifs.smb.client.password", "123456" );
		Config.setProperty( "jcifs.smb.client.soTimeout", "6000" );
        Config.setProperty( "jcifs.netbios.cachePolicy", "1200" );
        Config.setProperty( "jcifs.smb.lmCompatibility", "0" );
        Config.setProperty( "jcifs.smb.client.useExtendedSecurity", "false" );
        Config.setProperty( "jcifs.util.loglevel", "1" );
        enableBasic = Boolean.valueOf(
                Config.getProperty("jcifs.http.enableBasic")).booleanValue();
        insecureBasic = Boolean.valueOf(
                Config.getProperty("jcifs.http.insecureBasic")).booleanValue();
        realm = Config.getProperty("jcifs.http.basicRealm");

        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 );
        }
        if (realm == null) realm = "jCIFS";

        if(( level = Config.getInt( "jcifs.util.loglevel", -1 )) != -1 ) {
            LogStream.setLevel( level );
        }
        if( LogStream.level > 2 ) {
            try {
                Config.store( log, "JCIFS PROPERTIES" );
            } catch( IOException ioe ) {
            }
        }
	}
	
	
	/**
     * Negotiate password hashes with MSIE clients using NTLM SSP
     * @param req The servlet request
     * @param resp The servlet response
     * @param skipAuthentication If true the negotiation is only done if it is
     * initiated by the client (MSIE post requests after successful NTLM SSP
     * authentication). If false and the user has not been authenticated yet
     * the client will be forced to send an authentication (server sends
     * HttpServletResponse.SC_UNAUTHORIZED).
     * @return True if the negotiation is complete, otherwise false
     */
    public 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());

        if( msg != null && (msg.startsWith( "NTLM " ) ||
                    (offerBasic && msg.startsWith("Basic ")))) {
            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;
                }
                /* 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 {

                SmbSession.logon( dc, ntlm );
		//在catch 中做下修改 就不会弹出验证框了,直接当做验证失败跳到登录页面,我忘了有没有改了,反正是头信息,与源码对下吧
                if( LogStream.level > 2 ) {
                    log.println( "NtlmHttpFilter: " + ntlm +
                            " successfully authenticated against " + dc );
                }
            } catch( SmbAuthException sae ) {
                if( LogStream.level > 1 ) {
                    log.println( "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 + "\"");
                }
                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 ssn = req.getSession(false);
                if (ssn == null || (ntlm = (NtlmPasswordAuthentication)
                            ssn.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;
    }
}

 

  • 大小: 61.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics