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; } } }
相关阅读
微信扫描-捐赠支持
加入QQ群-技术交流
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑