SSO單點登陸實例

單點登陸流程圖html

 

 

系統登錄攔截器前端

//
// 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服務器登陸驗證代碼java

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";
    }
}
相關文章
相關標籤/搜索