SSM五:系统添加SSO单点登录

SSO:

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。比如用户登录了OA系统,再想进入公司的运营系统进行业务操作,有了SSO就不需重新登录,否则还要登录一次。


企业应用一般都需要权限管理系统,如果每个应用都自已搭一套权限管理系统,不但工作量大,也不能集中管理。SSO系统就是来解决这个问题的。

SSO的实现:

一般有两种实现方式,一种是每个需权限接口添加权限过滤标签(拦截器),另一种是对某个模式的url添加Filter。前者粒度较少,工作量大点,适用用户量大,对性能有严格要求的应用。后者粒度较大,工作量小,适用用户量小的管理系统。java可用SpringMVC,.net也有类似的框架。

对于SSO系统的客户端怎么鉴权?首先使用token作为登录的标识,客户端传到服务器的token与服务器的对比,如果一致就认为登录过了。多个系统都是这样判断。 有多种实现方式:

1.获取token,与数据库里的token对比。

2.获取token,与redis里的token对比。

3.获取token,与本地服务器的session里的token对比。

4.获取token,调用SSO系统的接口进行鉴权。

可以看见,上面4种并不是标准答案,还可以各种方案组合实现。

下面以方案3为例来实现一下sso客户端与服务器。


客户端过滤java实现:

package net.highesoft.ssm.filter;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;

import net.highesoft.ssm.util.CookieUtil;
import net.highesoft.ssm.util.HttpUtil;

@WebFilter(filterName = "AdminFilter",urlPatterns = "/*")
public class AdminFilter implements Filter{
	
	
    @Value("${sso.name}")
    private String ssoName;
    @Value("${sso.login}")
    private String loginUrl;
    @Value("${sso.query.user}")
    private String queryUserUrl;
	
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse rsp=(HttpServletResponse)response;
		
		String token=CookieUtil.getCookie(req,ssoName);
		
		String historyUrl=req.getParameter("historyUrl");
		if(StringUtils.isBlank(historyUrl)) {
			historyUrl=req.getRequestURL().toString();
		}
		historyUrl="?historyUrl="+historyUrl;
				
		if(StringUtils.isBlank(token)) {
			rsp.sendRedirect(loginUrl+historyUrl);
		}else {
			Object sessionToken=req.getSession().getAttribute(ssoName);
			if(sessionToken==null) {
				boolean rst=updateToken(req,rsp,historyUrl,token);
				if(rst) {
					chain.doFilter(request, response);
				}
			}else if(token.equals(sessionToken)){
				chain.doFilter(request, response);
			}else {
				//token不相等,重新登录
				req.getSession().removeAttribute(ssoName);
				rsp.sendRedirect(loginUrl+historyUrl);
			}
		}
		
	}
	private boolean updateToken(HttpServletRequest req,HttpServletResponse rsp,String historyUrl,String token) throws IOException {
		Map<String,String> headerMap=new HashMap<>();
		Enumeration<String> hnames=req.getHeaderNames();
		while(hnames.hasMoreElements()) {
			String name=hnames.nextElement();
			headerMap.put(name, req.getHeader(name));
		}
		String json=HttpUtil.doHttpPost(queryUserUrl, headerMap, new HashMap<>(), HttpUtil.PARAM_FORM);
		System.out.println(json);
		if(StringUtils.isBlank(json)) {
			rsp.sendRedirect(loginUrl+historyUrl);
			return false;
		}else {
			req.getSession().setAttribute(ssoName, token);
			return true;
		}
	}

}

客户端下载

服务端下载

文/程忠 浏览次数:0次   2019-11-25 10:49:28

相关阅读

微信扫描-捐赠支持
加入QQ群-技术交流

评论: