900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 单点登陆sso实现

单点登陆sso实现

时间:2019-08-17 00:23:02

相关推荐

单点登陆sso实现

需求:

多个bs业务系统,在某个业务系统登陆后,访问其他bs应用系统无需重复登陆.

制约:必须同一浏览器.

解决方案:

关键词:cookie,跨域,sso

环境

l 登陆认证服务l 病理业务系统l 检验业务系统

l login 拦截器:验证请求是否有令牌,令牌是否合法()

l 令牌 ticket

括号内为增强功能

l 用户访问,拦截器发现无令牌或令牌无效,跳转至的登陆页面(防止恶意测试密码,服务器生成登陆令牌到的cookie)

l 用户输入用户名,密码,发起请求(并携带登陆令牌,合法请求)到验证,验证通过,生成令牌,返回令牌-set cookie和需要sso的所有域名.

l ajax使用令牌发起跨域请求,传送令牌到各个业务系统,成功后重定向到/home页面

l 拦截器验证令牌合法性.不合法跳转到,合法返回页面给用户

l 用户继续访问,因为令牌已经设置完成,所以请求可以通过,无需登陆.

所有业务的Gateway与微服务都通过redis共享存储验证请求的合法性.实现业务系统的单点登录.

拦截器代码

@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {if(request.getServletPath().equals("/sso"))return true;this.getCache();Cookie[] cookies = request.getCookies();boolean checkFlag = false;if (cookies == null) {logger.error("请求的cookie为空,请启用cookie");checkFlag = false;} else {for (Cookie cookie : cookies) {if (cookie.getName().equals(Constants.TICKET)) {String ticket = cookie.getValue();checkFlag = true;}}}if (!checkFlag) {// 验证不通过String requestType = request.getHeader("x-requested-with");if ("XMLHttpRequest".equals(requestType)) {String contentType = "application/octet-stream";ServletOutputStream out = response.getOutputStream();response.setContentType(contentType);response.setHeader("sessionstatus", "timeout");out.print("<script>");out.print("windows.location.href='" + Constants.PASSPORT_LOGIN);out.print("</script>");out.flush();} else {response.sendRedirect(Constants.PASSPORT_LOGIN);}}return true;}

View Code

登陆验证

@RestController@RequestMapping("/login")public class LoginContronller {@AutowiredDictCacheHelper cache;@AutowiredSSOHelper sso;String[] servers = new String[] { "", "" };/*** 登陆验证 ,验证通过生成tictiket,并已tictiket为key保存用户权限信息,基本信息到redis.* * @param inParam* :userId,password,returnurl(验证通过后前往的页面,如果为空返回到用户有权访问的第一个系统)* @return 成功返回: ticket 要跳转到的系统 需要跨域的域名列表 验证不通过抛出异常.* @throws Exception */@RequestMapping("login") @ResponseBodypublic Map<String, Object> login(@RequestParam Map<String, Object> inParam,HttpServletRequest request, HttpServletResponse response) throws Exception {// 此处应调用后台服务获取用户权限信息.String userId= MapUtil.getValue("userId", inParam);if(!userId.equals("1"))throw new Exception(String.format("用户 %s 登陆验证失败,请输入正确的用户名密码", userId));String ticket = String.valueOf(System.currentTimeMillis()); // UUID.randomUUID();List<Map<String,Object>> userFuncs= new ArrayList<>();userFuncs.add(new MyMap().put("funcCode", "1001").getMap());userFuncs.add(new MyMap().put("funcCode", "1002").getMap());cache.setItem("ticket", ticket, new MyMap().put("userFuncs", userFuncs).getMap());Cookie cookie = new Cookie("ticket", ticket);// cookie.setDomain(request.getParameter("server"));cookie.setPath("/");// cookie.setMaxAge(10000000); response.addCookie(cookie);return new MyMap().put("ticket", ticket).put("servers", servers).getMap();}}

View Code

登陆js,登陆成功后会发起跨域请求,让需要sso的域名设置正确的cookie

var passport = {init : function() {$("#btnLogin").on("click",function() {$.ajax("login/login", {data : $('#loginForm').serialize(),error:function (XMLHttpRequest, textStatus, errorThrown) {$.messager.alert("操作失败",XMLHttpRequest.responseText);},dataType:"json",dataFilter:function (json, type) {var data = JSON.parse(json);for (var i = 0; i < data.servers.length; i++) {passport.crossAjax("http://" + data.servers[i]+ ':81/pis/sso', {'ticket' : data.ticket,'server' : data.servers[i]});};window.location.href = "http://" + data.servers[0]+ ':81/pis';},sucess : function(data) {alert(data);for (var i = 0; i < data.servers.length; i++) {passport.crossAjax("http://" + data.servers[i]+ ':81/pis/sso', {'ticket' : data.ticket,'server' : data.servers[i]});};window.location.href = "http://" + data.servers[0]+ ':81/pis';}});})},crossAjax : function(pageUrl, json, redirectFlag) {$.ajax({url : pageUrl,data : json,xhrFields : {withCredentials : true},crossDomain : true,async : false,timeout : 20 * 1000,})}}$(document).ready(function() {passport.init();});

业务系统收到sso请求

@RequestMapping(value = "/sso")public void doSSO(HttpServletRequest request, HttpServletResponse response) throws IOException {Cookie cookie = new Cookie("ticket", request.getParameter("ticket"));cookie.setDomain(request.getParameter("server"));cookie.setPath("/");// cookie.setMaxAge(10000000); response.addCookie(cookie);response.setContentType("text/plain");response.addHeader("P3P", "CP=CAO PSA OUR");response.getWriter().write(request.getParameter("server"));}

至此已实现单点登陆,主要思路参考京东单点登陆业务逻辑.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。