参考: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; } }
相关推荐
同父域sso单点登录源码SSO_SameFather
同域sso单点登录源码
jcifs实现SSO,SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是...
单点登录SSO解决方案之SpringSecurity+JWT实现.docx
单点登录 SSO单点登录 SSO单点登录 SSO单点登录 SSO
宁盾单点登录(SSO)与致远A8对接方案.pdf宁盾单点登录(SSO)与致远A8对接方案.pdf宁盾单点登录(SSO)与致远A8对接方案.pdf宁盾单点登录(SSO)与致远A8对接方案.pdf宁盾单点登录(SSO)与致远A8对接方案.pdf宁盾单点登录...
单点登录SSO的参考资料
sso单点登录ppt.ppt
宁盾单点登录(SSO)与SAP对接方案.docx宁盾单点登录(SSO)与SAP对接方案.docx宁盾单点登录(SSO)与SAP对接方案.docx宁盾单点登录(SSO)与SAP对接方案.docx宁盾单点登录(SSO)与SAP对接方案.docx宁盾单点登录(SSO)与SAP...
sso单点登录sso单点登录sso单点登录sso单点登录
跨服务器登录验证(单点登录SSO)过程和Java实现
讲述单点登录(SSO)常见的技术实现原理
单点登录(SSO)-同域名、不同域名
Teamcenter SSO单点登录配置步骤,包括客户端配置, web浏览器设置、服务器web服务设置、LDAP服务器设置等
因为公司要实现SSO单点登录的效果,最近在网上找了一些资料,但是都没有好用的, 所以自己用PHP 使用TP5.0 实现了SSO单点登录,可以跨多个域名。 下载后在本地配置好 A,B,C 3个网站,就可以模拟效果了。
sso单点登录源代码sso单点登录源代码sso单点登录源代码sso单点登录源代码sso单点登录源代码
Asp.net 单点登录SSO截HttpModel方法;决对实用好用的源码。 网上有很多sso,多数都是共享cookie,而这个是用在同一个iis下,截取httpmodel,修改User.Identity,记录它为用户信息可以到处用。 当然你也可修改扩展。。...
单点登录SSO,里面包括客户端和服务端,
discuz x2.5和cas集成,实现cas单点登录 SSO , php-5.2.14-Win32,Apache 2 2 ,PHPnow-1.5.6
跨服务器登录验证(单点登录SSO)的过程和Java实现.pdf