zoukankan      html  css  js  c++  java
  • SSO单点登录实例

    单点登录流程图

    系统登陆拦截器

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.jdcloud.policycloudapi.sso;
    
    import com.alibaba.fastjson.JSON;
    import com.jdcloud.policycloudapi.domain.response.RetResponse;
    import com.jdcloud.policycloudapi.domain.vo.LoginUser;
    import org.apache.commons.lang.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class SsoClientInterceptor implements HandlerInterceptor {
        private Logger log = LoggerFactory.getLogger(this.getClass());
        private SsoProperties ssoProperties;
        private RemoteService remoteService;
        public SsoClientInterceptor(SsoProperties ssoProperties, RemoteService remoteService) {
            this.ssoProperties = ssoProperties;
            this.remoteService = remoteService;
        }
    
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
            String tokenParam = null;
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for(int i = 0; i < cookies.length; ++i) {
                    if (cookies[i].getName().equals("gunsToken")) {
                        tokenParam = cookies[i].getValue();
                        break;
                    }
                }
            }
            if(!StringUtils.isNotBlank(tokenParam)){
                tokenParam=request.getParameter("gunsToken");
            }
    
    
            if (StringUtils.isNotBlank(tokenParam)) {
                //验证tokenParam是否正确
                Integer userId = this.remoteService.validateToken(tokenParam, HttpUtil.getRequestContextPath(request));
                if (userId != null) {
                    request.setAttribute("SESSION_LOGIN_FLAG", tokenParam);
    //              调用接口获取user,以及user权限列表
                    LoginUser loginUser=remoteService.getLoginUser(userId,tokenParam);
    //                log.info("loginUser:"+ JSON.toJSONString(loginUser));
    //                RestTemplateUtils restTemplateUtils=new RestTemplateUtils();
    //                LoginUser loginUser = restTemplateUtils.getLoginUser(tokenParam);
                    request.setAttribute(SsoConstants.LOGIN_USER_SESSION, loginUser);
                    return true;
                } else {
    //                this.redirectSsoServer(request, response);
                    return responseFalse(response);
                }
            } else {
    //            this.redirectSsoServer(request, response);
                return responseFalse(response);
            }
    //         return true;
        }
    
        private boolean responseFalse(HttpServletResponse response) throws IOException {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter out = null;
            out = response.getWriter();
            out.write(JSON.toJSONString(RetResponse.retFail()));
            out.flush();
            out.close();
            return false;
        }
    
        private void redirectSsoServer(HttpServletRequest request, HttpServletResponse response) {
            String redirectUrl = this.ssoProperties.getServerUrl() + "?" + "redirectUrl" + "=" + HttpUtil.encodeUrl(HttpUtil.getRequestFullPathNoParam(request));
    
            try {
                response.sendRedirect(redirectUrl);
            } catch (IOException var5) {
                this.log.error("跳转到服务器出错!", var5);
            }
    
        }
    
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        }
    
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        }
    }
    

     

    SSO服务器登录验证代码

    package com.stylefeng.sso.server.modular.controller;
    
    import com.stylefeng.guns.core.base.controller.BaseController;
    import com.stylefeng.guns.core.util.ToolUtil;
    import com.stylefeng.sso.plugin.constants.SsoConstants;
    import com.stylefeng.sso.plugin.service.AuthService;
    import com.stylefeng.sso.server.common.Rests;
    import com.stylefeng.sso.server.modular.entity.SysUser;
    import com.stylefeng.sso.server.modular.service.SysUserService;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    import static com.stylefeng.sso.plugin.constants.SsoConstants.LOGOUT_URL;
    
    
    /**
     * 登录验证控制器
     *
     * @author stylefeng
     * @Date 2018/2/3 22:23
     */
    @Controller
    @Slf4j
    public class AuthController extends BaseController {
    
        private static final String LOGIN_TIPS = "tips";
    
        @Autowired
        AuthService authService;
    
        @Autowired
        private SysUserService sysUserService;
    
        private boolean isMobile(HttpServletRequest request) {
            String userAgent = request.getHeader("User-Agent");
            userAgent = userAgent.toLowerCase();
            if (userAgent.contains("iphone") || userAgent.contains("android")
                    || userAgent.contains("ipad") || userAgent.contains("ipod")) {
                return true;
            }
            return false;
        }
    
        @RequestMapping (value = "/login", method = RequestMethod.GET)
        public String toLogin(HttpServletRequest request) {
            return isMobile(request)? "/login_m.html" : "/login.html";
        }
    
        @Value ("${spring.profiles.active}")
        private String profile;
    
        @RequestMapping (value = "/login", method = RequestMethod.POST)
        public String doLogin(HttpServletRequest request, HttpServletResponse response, Model model) {
    
            String returnUrl = isMobile(request)? "/login_m.html" : "/login.html";
    
            String tokenParam = null;
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (int i = 0; i < cookies.length; i++) {
                    if (cookies[i].getName().equals("gunsToken")) {
                        tokenParam = cookies[i].getValue();
                        break;
                    }
                }
            }
    
            String redirectUrl = request.getParameter(SsoConstants.REDIRECT_PARAM_NAME);
    
            // 如果cookie中能取到token,则认为从其他页面登录,不继续登录流程,跳回原地址
    //        if (StringUtils.isNotBlank(tokenParam) && StringUtils.isNotBlank(redirectUrl)){
    //            log.info("用户已经处于登录状态,不继续登录流程,跳回原地址: {}", redirectUrl);
    //            try {
    //                response.sendRedirect(redirectUrl);
    //                return null;
    //            } catch (IOException e) {
    //                log.warn("已经登录,跳回原地址失败", e);
    //                model.addAttribute(LOGIN_TIPS, "网络异常!");
    //                return "/login.html";
    //            }
    //        }
    
            String userName = request.getParameter("userName");
            String password = request.getParameter("password");
    
    
            // 登录失败是记录redirectUrl
            model.addAttribute(SsoConstants.REDIRECT_PARAM_NAME, redirectUrl);
            if (ToolUtil.isEmpty(userName) || ToolUtil.isEmpty(password) || ToolUtil.isEmpty(redirectUrl)) {
                model.addAttribute(LOGIN_TIPS, "请求信息不完整!");
                return returnUrl;
            } else {
    
                /**
                 * 判断用户账号密码是否正确
                 */
                Integer userId = authService.checkUserLogin(userName, password);
                if (userId != null) {
    
                    //如果账号密码正确,跳转回业务系统的url
                    String token = "";
                    try {
                    /*SysUser sysUser = sysUserService.getSysUser(userId);
                    sysUserService.insertLoginUserIntoRedisDto(sysUser, token);*/
                        token = authService.createToken(userId);
                    } catch (Exception e) {
                        log.warn("createToken失败",e);
                        model.addAttribute(LOGIN_TIPS, "登录失败,请稍后再试!");
                        return returnUrl;
                    }
    
                    if (profile.equals("dev")) {
                        Cookie localhost = new Cookie(SsoConstants.TOKEN_PARAM_NAME, token);
                        localhost.setDomain("jdcloud.com");
                        localhost.setPath("/");
                        localhost.setMaxAge(36000);
                        response.addCookie(localhost);
                    } else {
                        Cookie cookie = new Cookie(SsoConstants.TOKEN_PARAM_NAME, token);
                        cookie.setPath("/");
                        response.addCookie(cookie);
                    }
    
                    try {
    //                    String redirect=redirectUrl+"?"+SsoConstants.TOKEN_PARAM_NAME + "=" + token;
    //                    response.sendRedirect(redirectUrl /*+ "?" + SsoConstants.TOKEN_PARAM_NAME + "=" + token*/);
                        response.sendRedirect(redirectUrl);
                        return null;
                    } catch (IOException e) {
                        model.addAttribute(LOGIN_TIPS, "网络异常!");
                        return returnUrl;
                    }
                } else {
                    //如果账号密码错误
                    model.addAttribute(LOGIN_TIPS, "账号或密码错误!");
                    return returnUrl;
                }
            }
        }
    
        @ResponseBody
        @RequestMapping ("/hello")
        public String token() {
            return "暂未登录";
        }
    
        @RequestMapping (LOGOUT_URL)
        public String logout(HttpServletRequest request, HttpServletResponse response, Model model) {
            String tokenParam = null;
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (int i = 0; i < cookies.length; i++) {
                    if (cookies[i].getName().equals("gunsToken")) {
                        tokenParam = cookies[i].getValue();
                        break;
                    }
                }
            }
            String redirectUrl = request.getParameter(SsoConstants.REDIRECT_PARAM_NAME);
            if (StringUtils.isNotBlank(tokenParam)){
                // 删除redis中保存的token,如果失败,不允许退出登录,跳回源地址
                if (!authService.removeCachedToken(tokenParam)) {
                    try {
                        redirectUrl = redirectUrl + "?status="+SsoConstants.LOGIN_FAILED_FLAG+"?gunsToken"+tokenParam;
                        response.sendRedirect(redirectUrl);
                        return null;
                    } catch (Exception e) {
                        log.error("重定向失败", e);
                        return "/404.html";
                    }
                }
    
            }
    
            // 删除cookie
            // 开发环境为了方便前端本地测试配置域名hosts,cookie选择种到二级域下;线上环境域名一致,cookie种到默认的domain下
            if (profile.equals("dev")) {
                Cookie localhost = new Cookie(SsoConstants.TOKEN_PARAM_NAME, null);
                localhost.setPath("/");
                localhost.setMaxAge(0);
                response.addCookie(localhost);
            } else {
                Cookie newCookie = new Cookie(SsoConstants.TOKEN_PARAM_NAME, null); //假如要删除名称为username的Cookie
                newCookie.setMaxAge(0); //立即删除型
                newCookie.setPath("/"); //项目所有目录均有效,这句很关键,否则不敢保证删除
                response.addCookie(newCookie); //重新写入,将覆盖之前的
            }
    
            //跳转到登录页面
            model.addAttribute(SsoConstants.REDIRECT_PARAM_NAME, redirectUrl);
            return isMobile(request)? "/login_m.html" : "/login.html";
        }
    }
    

      

  • 相关阅读:
    使用qemu模拟调试内核和debian根文件系统
    qemu无界面启动,并重定向输出到终端
    linux 音频编程
    解决Android中No resource found that matches android:TextAppearance.Material.Widget.Button.Inverse问题
    【BigData】Java基础_通用排序工具类的实现
    【BigData】Java基础_登录注册实现
    【费曼学习方法】世界上最好的学习方法
    【BigData】Java基础_接口
    【BigData】Java基础_Eclipse配置自动补全new
    【BigData】Java基础_HashSet
  • 原文地址:https://www.cnblogs.com/e206842/p/11770024.html
Copyright © 2011-2022 走看看