参考:http://jusescn.iteye.com/blog/757475,http://www.iteye.com/problems/61029
以及其他网上资料
1.概念
单点登录:http://baike.baidu.com/view/993620.htm,http://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; } }
相关推荐
2. **会话管理**:jcifs提供会话管理功能,能够在用户成功登录后保存其凭证,以便在后续请求中复用,从而实现SSO的效果。 3. **资源共享**:jcifs允许Java应用访问和操作Windows网络共享,如读取、写入文件,创建...
同域SSO特指在相同域名下的多个子系统之间实现单点登录,这对于大型网站或者企业内部应用集群尤为实用。下面将详细阐述同域SSO单点登录的核心概念、实现原理以及关键步骤。 1. **核心概念** - **票据(Ticket)**...
SSO(Single Sign-On)单点登录是一种身份验证机制,允许用户在一次登录后访问多个相互关联的应用系统,而无需再次进行身份验证。在“同父域”环境下,这意味着所有相关应用都共享相同的顶级域名,比如`example.com`...
为了让自定义登录页面能够与CAS服务器进行SSO交互,你需要确保页面中包含一个隐藏的IFRAME元素,用于接收来自CAS的重定向。此外,还需要监听IFRAME的加载事件,以便处理服务票据。 五、安全考虑 在实现自定义登录...
### Teamcenter 11 SSO单点登录配置详解 #### 一、概述 Teamcenter 11 SSO(Single Sign-On)单点登录配置是指在Teamcenter系统中实现用户通过域账号和密码来替代原有的Teamcenter账号及密码的过程。这种配置能够...
4. **SAML(Security Assertion Markup Language)**:另一种常见的SSO协议,用于在不同的安全域之间传递用户认证和授权信息。SAML令牌包含了用户的身份信息,可以跨域传输。 5. **OAuth2.0 和 OpenID Connect**:...
jcifs实现SSO,SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是...
jcifs-ext-0.9.4.jar便是这样一个关键的拓展包,它为Java应用程序提供了与Windows网络身份验证交互的能力,特别是在实施单点登录(Single Sign-On, SSO)系统如CAS(Central Authentication Service)时。...
单点登录(Single Sign-On,简称SSO)是一种认证机制,允许用户仅通过一次登录就能访问同一域下的多个应用程序和服务。这种机制简化了用户的使用体验,并提升了系统的整体安全性。 #### 二、单点登录的基本运行机制...
6. **自定义登录页面**:设计自定义登录页面,与SSO中心进行交互。 7. **处理授权**:配置访问控制规则,根据用户角色和权限决定其可访问的资源。 以上只是简单概述了SSO的基本概念和Java实现,实际应用中可能涉及...
单点登录 SSO单点登录 SSO单点登录 SSO单点登录 SSO
3. 实现单点登录(SSO): 在拥有自身系统登录界面的场景下,可以借助FineReport实现单点登录。具体操作包括在用户自己的系统登录页面(login.jsp)中引入finereport.js,并通过JavaScript定义相关的登录逻辑,将...
1. **Cookie域的设置**:在SSO系统中登录后,可以通过设置Cookie的域为顶级域(如`.example.com`),使得所有子域都能访问到该Cookie。这解决了Cookie跨域的问题。 2. **Session共享**:虽然各应用系统间默认不会...
CAS(Central Authentication Service,中央认证服务)是一种广泛使用的开源身份验证框架,主要用于实现单点登录(Single Sign-On,SSO)。在本主题中,我们将深入探讨如何在CAS中进行自定义加密和登录验证。 首先...
sso单点登录ppt.ppt
单点登录SSO的实现原理 单点登录(SSO)是一种常见的技术实现原理,在多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。实现单点登录说到底就是要...
单点登录(Single Sign-On,简称SSO)是一种身份验证机制,它允许用户在一个系统上登录后,无需再次输入凭证即可访问多个相互关联的系统。SSO的主要目标是提高用户体验,减少用户记忆多个密码的负担,同时也能提高...
在ASP.NET中,可以使用Forms Authentication或Windows Authentication,但通常Forms Authentication更适合跨域身份验证,因为它允许自定义登录逻辑和令牌生成。 2. **票据(Ticket)管理**:登录成功后,系统会生成...
SSO(Single Sign-On)单点登录是一种网络认证机制,允许用户在一次登录后,就能访问多个相互关联的应用系统,而无需再次输入凭证。...同时,也可以借鉴其中的设计模式和最佳实践,为自定义的SSO解决方案提供参考。