虚拟化技术Ovirt

【Ovirt 笔记】单点登录分析与整理

2018-06-06  本文已影响8人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 4.2.3 版本。

1. 概念

1.1 单点登录

1.2 CORS 定义

<dependency>
   <groupId>org.ebaysf.web</groupId>
   <artifactId>cors-filter</artifactId>
   <version>1.0.1</version>
</dependency>

2. 分析与整理

2.1 用户直接登录管理门户

用户直接登录管理门户流程
模块 描述
webadmin 管理门户
enginesso SSO 认证中心
SsoLoginFilter 判断 SsoSession 是否存在,ovirt_aaa_engineSessionId 的值是否存在。
SsoLoginServlet 组装授权参数,client_id=ovirt-engine-core,response_type=code,app_url=<webadmin_url>,scope=ovirt-app-admin ovirt-app-portal ovirt-ext=auth:sequence-priority=~,source_addr=<client_ipaddr>
OAuthAuthorizeServlet 创建 SsoSession,将上一个步骤传递的参数保存到 session 中,组装访问域栈 AuthStack。
InteractiveNextAuthServlet 访问域认证,取出栈中数据,依次认证。
InteractiveNegotiateAuthServlet 外部域认证,从数据库中查询用户是否登录等信息。
InteractiveAuthServlet 内部域认证,未登录抛出异常,转向登录 SSO 认证中心登录界。根据传递的用户名和密码,进行 SSO 认证中心登录认证,认证通过创建用户资格证书,处理资格证书,从数据库中查询用户信息,设置到 SsoSession 中,创建 Token 和 authCode,建立 Token 与 SsoSession 的映射表,将 Token 和 authCode 设置到 SsoSession 中。
InteractiveRedirectToModuleServlet 封装转向业务系统的授权请求。code=<authCode>,app_url=<webadmin_url>,state=authenticated。
SsoPostLoginServlet 处理授权信息。通过 authCode 获取 Token。创建业务系统自身 Session。
OAuthTokenServlet SsoPostLoginServlet 中执行通过 authCode 获取 Token 的步骤。是一个模拟请求。
OAuthTokenInfoServlet SsoPostLoginServlet 中执行通过 Token 获取用户信息等(从 SsoSession 中获取)的步骤。是一个模拟请求。

2.1.1 用户选择管理门户

<webModule>
       <groupId>org.ovirt.engine.ui</groupId>
       <artifactId>webadmin</artifactId>
       <bundleFileName>webadmin.war</bundleFileName>
       <contextRoot>/ovirt-engine/webadmin</contextRoot>
</webModule>
<filter>
     <filter-name>SsoLoginFilter</filter-name>
     <filter-class>org.ovirt.engine.core.aaa.filters.SsoLoginFilter</filter-class>
     <init-param>
         <param-name>login-url</param-name>
         <param-value>/sso/login?</param-value>
     </init-param>
</filter>
......
<filter-mapping>
     <filter-name>SsoLoginFilter</filter-name>
     <url-pattern>/WebAdmin.html</url-pattern>
</filter-mapping>
......
<welcome-file-list>
     <welcome-file>WebAdmin.html</welcome-file>
</welcome-file-list>
public static final String HTTP_SESSION_ENGINE_SESSION_ID_KEY = "ovirt_aaa_engineSessionId";
......
if (!FiltersHelper.isAuthenticated(req) || !FiltersHelper.isSessionValid((HttpServletRequest) request)) {
                String url = String.format("%s%s&app_url=%s&locale=%s",
                        req.getServletContext().getContextPath(),
                        loginUrl,
                        URLEncoder.encode(requestURL.toString(), "UTF-8"),
                        request.getAttribute("locale").toString());
                log.debug("Redirecting to {}", url);
                res.sendRedirect(url);
......
public static boolean isAuthenticated(HttpServletRequest request) {
        return (request.getSession(false) != null && request.getSession(false)
                .getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY) != null)
                || request.getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY) != null;
}
<servlet>
     <servlet-name>login</servlet-name>
     <servlet-class>org.ovirt.engine.core.aaa.servlet.SsoLoginServlet</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>login</servlet-name>
     <url-pattern>/sso/login</url-pattern>
</servlet-mapping>
URLBuilder urlBuilder = new URLBuilder(FiltersHelper.getEngineSsoUrl(request), "/oauth/authorize")
                .addParameter("client_id", EngineLocalConfig.getInstance().getProperty("ENGINE_SSO_CLIENT_ID"))
                .addParameter("response_type", "code")
                .addParameter("app_url", request.getParameter("app_url"))
                .addParameter("engine_url", FiltersHelper.getEngineUrl(request))
                .addParameter("redirect_uri", redirectUri)
                .addParameter("scope", scope)
                .addParameter("source_addr", request.getRemoteAddr());
 <context-param>
     <param-name>post-action-url</param-name>
     <param-value>/ovirt-engine/webadmin/sso/oauth2-callback</param-value>
</context-param>
<context-param>
     <param-name>auth-seq-priority-property-name</param-name>
     <param-value>ENGINE_SSO_AUTH_SEQUENCE_webadmin</param-value>
</context-param>
[root@rhvm ~]# cat /usr/share/ovirt-engine/services/ovirt-engine/ovirt-engine.conf | grep ENGINE_SSO_AUTH_SEQUENCE_webadmin
ENGINE_SSO_AUTH_SEQUENCE_webadmin=~
<webModule>
     <groupId>org.ovirt.engine.core</groupId>
     <artifactId>enginesso</artifactId>
     <bundleFileName>enginesso.war</bundleFileName>
     <contextRoot>/ovirt-engine/sso</contextRoot>
</webModule>
<filter>
    <filter-name>CORSSupport</filter-name>
    <filter-class>org.ovirt.engine.core.utils.servlet.CORSSupportFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CORSSupport</filter-name>
    <url-pattern>/sso/*</url-pattern>
</filter-mapping>
<servlet>
    <servlet-name>OAuthAuthorizeServlet</servlet-name>
    <servlet-class>org.ovirt.engine.core.sso.servlets.OAuthAuthorizeServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>OAuthAuthorizeServlet</servlet-name>
    <url-pattern>/oauth/authorize</url-pattern>
</servlet-mapping>
protected SsoSession buildSsoSession(HttpServletRequest request)
            throws Exception {
        String clientId = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_CLIENT_ID);
        String scope = SsoUtils.getScopeRequestParameter(request, "");
        String state = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_STATE, "");
        String appUrl = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_APP_URL, "");
        String engineUrl = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_ENGINE_URL, "");
        String redirectUri = request.getParameter(SsoConstants.HTTP_PARAM_REDIRECT_URI);
        String sourceAddr = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_SOURCE_ADDR, "UNKNOWN");
        validateClientRequest(request, clientId, scope, redirectUri);

        // Create the session
        request.getSession(true);

        SsoSession ssoSession = SsoUtils.getSsoSession(request);
        ssoSession.setAppUrl(appUrl);
        ssoSession.setClientId(clientId);
        ssoSession.setSourceAddr(sourceAddr);
        ssoSession.setRedirectUri(redirectUri);
        ssoSession.setScope(scope);
        ssoSession.setState(state);
        ssoSession.getHttpSession().setMaxInactiveInterval(-1);

        if (StringUtils.isNotEmpty(engineUrl)) {
            ssoSession.setEngineUrl(engineUrl);
        } else {
            ssoSession.setEngineUrl(SsoUtils.getSsoContext(request).getEngineUrl());
        }

        return ssoSession;
}
protected Stack<InteractiveAuth> getAuthSeq(SsoSession ssoSession) {
        String scopes = ssoSession.getScope();
        String appAuthSeq = ssoContext.getSsoLocalConfig().getProperty("SSO_AUTH_LOGIN_SEQUENCE");

        String authSeq = null;
        if (StringUtils.isEmpty(scopes) || !scopes.contains("ovirt-ext=auth:sequence-priority=")) {
            authSeq = "~";
        } else {
            for (String scope : SsoUtils.scopeAsList(scopes)) {
                if (scope.startsWith("ovirt-ext=auth:sequence-priority=")) {
                    String[] tokens = scope.trim().split("=", 3);
                    authSeq = tokens[2];
                }
            }
        }

        List<InteractiveAuth> authSeqList = getAuthListForSeq(authSeq);

        if (StringUtils.isNotEmpty(authSeq) && authSeq.startsWith("~")) {
            // get unique auth seq
            for (char c : appAuthSeq.toCharArray()) {
                if (!authSeqList.contains(InteractiveAuth.valueOf("" + c))) {
                    authSeqList.add(InteractiveAuth.valueOf("" + c));
                }
            }
            // intersect auth seq with sso auth seq settings
            authSeqList.retainAll(getAuthListForSeq(appAuthSeq));
        }
        Collections.reverse(authSeqList);
        Stack<InteractiveAuth> authSeqStack = new Stack<>();
        authSeqStack.addAll(authSeqList);
        return authSeqStack;
}

......

ssoSession.setAuthStack(getAuthSeq(ssoSession));
[root@rhvm ~]# cat /usr/share/ovirt-engine/services/ovirt-engine/ovirt-engine.conf | grep SSO_AUTH_LOGIN_SEQUENCE
SSO_AUTH_LOGIN_SEQUENCE=NI
I {
        @Override
        public String getName() {
            return "Internal";
        }

        @Override
        public String getAuthUrl(HttpServletRequest request, HttpServletResponse response) {
            log.debug("Redirecting to Internal Auth Servlet");
            return request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_URI;
        }
    },
    N {
        @Override
        public String getName() {
            return "Negotiate";
        }

        @Override
        public String getAuthUrl(HttpServletRequest request, HttpServletResponse response) {
            log.debug("Redirecting to External Auth Servlet");
            return request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_NEGOTIATE_URI;
        }
};
public static final String INTERACTIVE_LOGIN_NEXT_AUTH_URI = "/interactive-login-next-auth";
......
ssoSession.setAuthStack(getAuthSeq(ssoSession));
            if (ssoSession.getAuthStack().isEmpty()) {
                throw new OAuthException(SsoConstants.ERR_CODE_ACCESS_DENIED,
                        ssoContext.getLocalizationUtils().localize(
                                SsoConstants.APP_ERROR_NO_VALID_AUTHENTICATION_MECHANISM_FOUND,
                                (Locale) request.getAttribute(SsoConstants.LOCALE)));
            }
            redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_NEXT_AUTH_URI;
<servlet>
    <servlet-name>InteractiveNextAuthServlet</servlet-name>
    <servlet-class>org.ovirt.engine.core.sso.servlets.InteractiveNextAuthServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>InteractiveNextAuthServlet</servlet-name>
    <url-pattern>/interactive-login-next-auth</url-pattern>
</servlet-mapping>
<servlet>
        <servlet-name>InteractiveNegotiateAuthServlet</servlet-name>
        <servlet-class>org.ovirt.engine.core.sso.servlets.InteractiveNegotiateAuthServlet</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>InteractiveNegotiateAuthServlet</servlet-name>
        <url-pattern>/interactive-login-negotiate/*</url-pattern>
</servlet-mapping>
protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        switch (SsoUtils.getSsoContext(request).getNegotiateAuthUtils().doAuth(request, response).getStatus()) {
            case Authn.AuthResult.NEGOTIATION_UNAUTHORIZED:
                log.debug("External authentication failed redirecting to url: {}",
                        SsoConstants.INTERACTIVE_LOGIN_NEXT_AUTH_URI);
                response.sendRedirect(request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_NEXT_AUTH_URI);
                break;
            case Authn.AuthResult.SUCCESS:
                log.debug("External authentication succeeded redirecting to module");
                response.sendRedirect(request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI);
                break;
            case Authn.AuthResult.NEGOTIATION_INCOMPLETE:
                log.debug("External authentication incomplete");
                break;
        }
}
response.sendRedirect(authStack.pop().getAuthUrl(request, response));
public static final String INTERACTIVE_LOGIN_URI = "/interactive-login";
......
@Override
public String getAuthUrl(HttpServletRequest request, HttpServletResponse response) {
     log.debug("Redirecting to Internal Auth Servlet");
     return request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_URI;
}
<servlet>
   <servlet-name>InteractiveAuthServlet</servlet-name>
   <servlet-class>org.ovirt.engine.core.sso.servlets.InteractiveAuthServlet</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>InteractiveAuthServlet</servlet-name>
   <url-pattern>/interactive-login</url-pattern>
</servlet-mapping>
if (ssoSession == null) {
   throw new OAuthException(SsoConstants.ERR_CODE_INVALID_GRANT, ssoContext.getLocalizationUtils().localize(SsoConstants.APP_ERROR_SESSION_EXPIRED, (Locale) request.getAttribute(SsoConstants.LOCALE)));
public static final String INTERACTIVE_LOGIN_FORM_URI = "/login.html";
......
redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_FORM_URI;
......
if (redirectUrl != null) {
     response.sendRedirect(redirectUrl);
}
<servlet>
     <servlet-name>LoginForm</servlet-name>
     <jsp-file>/WEB-INF/login.jsp</jsp-file>
</servlet>

<servlet-mapping>
     <servlet-name>LoginForm</servlet-name>
     <url-pattern>/login.html</url-pattern>
</servlet-mapping>

2.1.2 用户登录 SSO 认证中心

<form class="form-horizontal" id="loginForm" method="post" action="${pageContext.request.contextPath}/interactive-login">
private Credentials getUserCredentials(HttpServletRequest request) throws Exception {
        String username = SsoUtils.getFormParameter(request, USERNAME);
        String password = SsoUtils.getFormParameter(request, PASSWORD);
        String profile = SsoUtils.getFormParameter(request, PROFILE);
        Credentials credentials;
        // The code is invoked from the login screen as well as when the user changes password.
        // If the login form parameters are not present the code has been invoked from change password flow and
        // we extract the credentials from the credentials saved to sso session.
        if (username == null || password == null || profile == null) {
            credentials = SsoUtils.getSsoSession(request).getTempCredentials();
        } else {
            credentials = new Credentials(username, password, profile, ssoContext.getSsoProfiles().contains(profile));
        }
        return credentials;
}
redirectUrl = authenticateUser(request, response, userCredentials);
......
private String authenticateUser(
            HttpServletRequest request,
            HttpServletResponse response,
            Credentials userCredentials) throws ServletException, IOException, AuthenticationException {
     ......
     AuthenticationUtils.handleCredentials(ssoContext, request, userCredentials);
}
SsoSession ssoSession = login(ssoContext, request, credentials, null, interactive);
public static SsoSession persistAuthInfoInContextWithToken(
            HttpServletRequest request,
            String password,
            String profileName,
            ExtMap authRecord,
            ExtMap principalRecord) throws Exception {
        String validTo = authRecord.get(Authn.AuthRecord.VALID_TO);
        String authCode = generateAuthorizationToken();
        String accessToken = generateAuthorizationToken();

        SsoSession ssoSession = getSsoSession(request, true);
        ssoSession.setAccessToken(accessToken);
        ssoSession.setAuthorizationCode(authCode);

        request.setAttribute(SsoConstants.HTTP_REQ_ATTR_ACCESS_TOKEN, accessToken);

        ssoSession.setActive(true);
        ssoSession.setAuthRecord(authRecord);
        ssoSession.setAutheticatedCredentials(ssoSession.getTempCredentials());
        getSsoContext(request).registerSsoSession(ssoSession);

        ssoSession.setPrincipalRecord(principalRecord);
        ssoSession.setProfile(profileName);
        ssoSession.setStatus(SsoSession.Status.authenticated);
        ssoSession.setTempCredentials(null);
        ssoSession.setUserId(getUserId(principalRecord));
        try {
            ssoSession.setValidTo(validTo == null ?
                    Long.MAX_VALUE : new SimpleDateFormat("yyyyMMddHHmmssZ").parse(validTo).getTime());
        } catch (Exception ex) {
            log.error("Unable to parse Auth Record valid_to value: {}", ex.getMessage());
            log.debug("Exception", ex);
        }

        persistUserPassword(request, ssoSession, password);

        ssoSession.touch();
        return ssoSession;
}
public static final String INTERACTIVE_REDIRECT_TO_MODULE_URI = "/interactive-redirect-to-module";
......
return request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI;
......
if (redirectUrl != null) {
     response.sendRedirect(redirectUrl);
}
<servlet>
    <servlet-name>InteractiveRedirectToModuleServlet</servlet-name>
    <servlet-class>org.ovirt.engine.core.sso.servlets.InteractiveRedirectToModuleServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>InteractiveRedirectToModuleServlet</servlet-name>
    <url-pattern>/interactive-redirect-to-module</url-pattern>
</servlet-mapping>
public static void redirectToModule(HttpServletRequest request,
                                        HttpServletResponse response)
            throws IOException {
        log.debug("Entered redirectToModule");
        try {
            SsoSession ssoSession = getSsoSession(request);
            URLBuilder redirectUrl = new URLBuilder(getRedirectUrl(request))
                    .addParameter("code", ssoSession.getAuthorizationCode());
            String appUrl = ssoSession.getAppUrl();
            if (StringUtils.isNotEmpty(appUrl)) {
                redirectUrl.addParameter("app_url", appUrl);
            }
            String state = ssoSession.getState();
            if (StringUtils.isNotEmpty(state)) {
                redirectUrl.addParameter("state", state);
            }
            String url = redirectUrl.build();
            response.sendRedirect(url);
            log.debug("Redirecting back to module: {}", url);
        } catch (Exception ex) {
            log.error("Error redirecting back to module: {}", ex.getMessage());
            log.debug("Exception", ex);
            throw new RuntimeException(ex);
        } finally {
            getSsoSession(request).cleanup();
        }
 }
public static String getRedirectUrl(HttpServletRequest request) throws Exception {
        String uri = getSsoSession(request, true).getRedirectUri();
        return StringUtils.isEmpty(uri) ?
                new URLBuilder(getSsoContext(request).getEngineUrl(), "/oauth2-callback").build()  : uri;
}
<servlet>
     <servlet-name>SsoPostLoginServlet</servlet-name>
     <servlet-class>org.ovirt.engine.core.aaa.servlet.SsoPostLoginServlet</servlet-class>
     <init-param>
        <param-name>login-as-admin</param-name>
        <param-value>true</param-value>
     </init-param>
</servlet>
<servlet-mapping>
     <servlet-name>SsoPostLoginServlet</servlet-name>
     s<url-pattern>/sso/oauth2-callback</url-pattern>
</servlet-mapping>
<listener>
     <listener-class>org.ovirt.engine.core.sso.context.SsoContextListener</listener-class>
</listener>
ssoContext.setSsoClientRegistry(DBUtils.getAllSsoClientsInfo());
Map<String, Object> response = SsoOAuthServiceUtils.getToken("authorization_code", authCode, scope, redirectUri);
FiltersHelper.isStatusOk(response);
public static Map<String, Object> getToken(String grantType, String code, String scope, String redirectUri) {
        try {
            HttpPost request = createPost("/oauth/token");
            setClientIdSecretBasicAuthHeader(request);
            List<BasicNameValuePair> form = new ArrayList<>(4);
            form.add(new BasicNameValuePair("grant_type", grantType));
            form.add(new BasicNameValuePair("code", code));
            form.add(new BasicNameValuePair("redirect_uri", redirectUri));
            form.add(new BasicNameValuePair("scope", scope));
            request.setEntity(new UrlEncodedFormEntity(form, StandardCharsets.UTF_8));
            return getResponse(request);
        } catch (Exception ex) {
            return buildMapWithError("server_error", ex.getMessage());
        }
}
private static void setClientIdSecretBasicAuthHeader(HttpUriRequest request) {
        EngineLocalConfig config = EngineLocalConfig.getInstance();
        byte[] encodedBytes = Base64.encodeBase64(String.format("%s:%s",
                config.getProperty("ENGINE_SSO_CLIENT_ID"),
                config.getProperty("ENGINE_SSO_CLIENT_SECRET")).getBytes());
        request.setHeader(FiltersHelper.Constants.HEADER_AUTHORIZATION, String.format("Basic %s", new String(encodedBytes)));
}
<servlet>
        <servlet-name>OAuthTokenServlet</servlet-name>
        <servlet-class>org.ovirt.engine.core.sso.servlets.OAuthTokenServlet</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>OAuthTokenServlet</servlet-name>
        <url-pattern>/oauth/token</url-pattern>
</servlet-mapping>
case "authorization_code":
                issueTokenForAuthCode(request, response, scope);
                break;
......
protected void issueTokenForAuthCode(
            HttpServletRequest request,
            HttpServletResponse response,
            String scope) throws Exception {
        String[] clientIdAndSecret = SsoUtils.getClientIdClientSecret(request);
        SsoUtils.validateClientRequest(request,
                clientIdAndSecret[0],
                clientIdAndSecret[1],
                scope,
                null);
        SsoSession ssoSession = handleIssueTokenForAuthCode(request, clientIdAndSecret[0], scope);
        log.debug("Sending json response");
        SsoUtils.sendJsonData(response, buildResponse(ssoSession));
}

protected Map<String, Object> buildResponse(SsoSession ssoSession) {
        Map<String, Object> payload = new HashMap<>();
        payload.put(SsoConstants.JSON_ACCESS_TOKEN, ssoSession.getAccessToken());
        payload.put(SsoConstants.JSON_SCOPE, StringUtils.isEmpty(ssoSession.getScope()) ? "" : ssoSession.getScope());
        payload.put(SsoConstants.JSON_EXPIRES_IN, ssoSession.getValidTo().toString());
        payload.put(SsoConstants.JSON_TOKEN_TYPE, "bearer");
        return payload;
}
<servlet>
        <servlet-name>OAuthTokenInfo</servlet-name>
        <servlet-class>org.ovirt.engine.core.sso.servlets.OAuthTokenInfoServlet</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>OAuthTokenInfo</servlet-name>
        <url-pattern>/oauth/token-info</url-pattern>
</servlet-mapping>
private Map<String, Object> buildResponse(SsoSession ssoSession, String password) {
        Map<String, Object> payload = new HashMap<>();
        payload.put(SsoConstants.JSON_ACTIVE, ssoSession.isActive());
        payload.put(SsoConstants.JSON_TOKEN_TYPE, "bearer");
        payload.put(SsoConstants.JSON_CLIENT_ID, ssoSession.getClientId());
        payload.put(SsoConstants.JSON_USER_ID, ssoSession.getUserIdWithProfile());
        payload.put(SsoConstants.JSON_SCOPE, StringUtils.isEmpty(ssoSession.getScope()) ? "" : ssoSession.getScope());
        payload.put(SsoConstants.JSON_EXPIRES_IN, ssoSession.getValidTo().toString());

        Map<String, Object> ovirt = new HashMap<>();
        ovirt.put("version", SsoConstants.OVIRT_SSO_VERSION);
        ovirt.put("principal_id", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.ID));
        ovirt.put("email", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.EMAIL));
        ovirt.put("namespace", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.NAMESPACE));
        ovirt.put("first_name", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.FIRST_NAME));
        ovirt.put("last_name", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.LAST_NAME));
        ovirt.put("group_ids", ssoSession.getPrincipalRecord().<Collection>get(Authz.PrincipalRecord.GROUPS,
            Collections.<ExtMap>emptyList()));
        if (password != null) {
            ovirt.put("password", password);
        }
        ovirt.put("capability_credentials_change",
                ssoContext.getSsoProfilesSupportingPasswdChange().contains(ssoSession.getProfile()));
        payload.put("ovirt", ovirt);
        return payload;
}
ActionReturnValue queryRetVal = FiltersHelper.getBackend(ctx).runAction(ActionType.CreateUserSession,
                        new CreateUserSessionParameters(
                                (String) jsonResponse.get(SessionConstants.SSO_TOKEN_KEY),
                                (String) jsonResponse.get(SessionConstants.SSO_SCOPE_KEY),
                                appScope,
                                profile,
                                username,
                                (String) payload.get("principal_id"),
                                (String) payload.get("email"),
                                (String) payload.get("first_name"),
                                (String) payload.get("last_name"),
                                (String) payload.get("namespace"),
                                request.getRemoteAddr(),
                                (Collection<ExtMap>) payload.get("group_ids"),
                                loginAsAdmin));
httpSession.setAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY,
queryRetVal.getActionReturnValue());
httpSession.setAttribute(FiltersHelper.Constants.REQUEST_LOGIN_FILTER_AUTHENTICATION_DONE, true);
log.debug("Redirecting to '{}'", appUrl);
response.sendRedirect(appUrl);
<servlet-mapping>
     <servlet-name>WebAdminHostPageServlet</servlet-name>
     <url-pattern>/WebAdmin.html</url-pattern>
</servlet-mapping>

2.2 用户先登录 SSO 认证中心

用户先登录 SSO 认证中心流程

2.2.1 用户首先登录 SSO 认证中心

<servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>org.ovirt.engine.core.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
</servlet-mapping>
response.sendRedirect(
                    new URLBuilder(FiltersHelper.getEngineSsoUrl(request),
                            WelcomeUtils.OAUTH_AUTHORIZE_URI)
                    .addParameter(WelcomeUtils.HTTP_PARAM_CLIENT_ID,
                            EngineLocalConfig.getInstance().getProperty(WelcomeUtils.ENGINE_SSO_CLIENT_ID))
                    .addParameter(WelcomeUtils.HTTP_PARAM_RESPONSE_TYPE, WelcomeUtils.CODE)
                    .addParameter(WelcomeUtils.HTTP_PARAM_ENGINE_URL, FiltersHelper.getEngineUrl(request))
                    .addParameter(WelcomeUtils.HTTP_PARAM_REDIRECT_URI, WelcomeUtils.getOauth2CallbackUrl(request))
                    .addParameter(WelcomeUtils.HTTP_PARAM_SCOPE, request.getParameter(WelcomeUtils.SCOPE))
                    .addParameter(WelcomeUtils.HTTP_PARAM_LOCALE, request.getAttribute(WelcomeUtils.LOCALE).toString())
                    .addParameter(WelcomeUtils.HTTP_PARAM_SOURCE_ADDR, request.getRemoteAddr())
                    .build());
public static String getRedirectUrl(HttpServletRequest request) throws Exception {
        String uri = getSsoSession(request, true).getRedirectUri();
        return StringUtils.isEmpty(uri) ?
                new URLBuilder(getSsoContext(request).getEngineUrl(), "/oauth2-callback").build()  : uri;
}
 <servlet>
        <servlet-name>OAuthCallbackServlet</servlet-name>
        <servlet-class>org.ovirt.engine.core.OAuthCallbackServlet</servlet-class>
</servlet>
<servlet-mapping>
        <servlet-name>OAuthCallbackServlet</servlet-name>
        <url-pattern>/oauth2-callback</url-pattern>
</servlet-mapping>
String engineUri = EngineLocalConfig.getInstance().getProperty(WelcomeUtils.ENGINE_URI) + "/";
......
response.sendRedirect(engineUri);

2.2.2 再选择管理门户

if (SsoUtils.isUserAuthenticated(request)) {
            log.debug("User is authenticated redirecting to interactive-redirect-to-module");
            redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI;

3. 总结整理

用户认证流程
<listener>
    <listener-class>org.ovirt.engine.core.sso.context.SsoSessionListener</listener-class>
</listener>
@Override
public void sessionCreated(HttpSessionEvent se) {
    se.getSession().setAttribute(SsoConstants.OVIRT_SSO_SESSION, new SsoSession(se.getSession()));
}

@Override
public void sessionDestroyed(HttpSessionEvent se) {
    TokenCleanupUtility.cleanupExpiredTokens(se.getSession().getServletContext());
}
上一篇下一篇

猜你喜欢

热点阅读