Aplicação do fluxo da mola da análise de configuração do processo de saída do CAS

Contexto: recebi hoje um pedido de que o cas pode ser redirecionado para qualquer site da Web. Recomenda-se realizar uma correspondência regular estrita no URL redirecionado ou não usar os parâmetros passados ​​do front end como base para o redirecionamento.

1. Pessoas preguiçosas olham primeiro

O redirecionamento do logout do cas ainda é muito bom em termos de design.Já ajudou você a considerar o controle de segurança do escopo do redirecionamento do logout.O problema mencionado no fundo é totalmente causado por nossa configuração inadequada.
Então, como o CAS habilita o controle de segurança de redirecionamento?
Muito simples, basta cas.logout.followServiceRedirectsdefinir como verdadeiro; o padrão do sistema é falso.

##
# CAS Logout Behavior
# WEB-INF/cas-servlet.xml
#
# Specify whether CAS should redirect to the specified service parameter on /logout requests
cas.logout.followServiceRedirects=true

Então, como o CAS realiza o controle de segurança de redirecionamento?
A seguir, vamos dar uma olhada no controle de processo do CAS com o Sr. Zihan ~

Em segundo lugar, controle de processo de logout cas

Sabemos que os processos de login e logout do cas são definidos por login-webflow.xml e logout-webflow.xml respectivamente.

1. Entenda o Spring Webflow

A pilha de tecnologia usada pela definição do processo de logout do cas é Spring webflow, o endereço do site oficial . Por exemplo, decision-stateseleção de processos e action-statecomponentes de execução:

  • Selecione os componentes
	<decision-state id="serviceCheck">
		<if test="flowScope.service != null" then="generateServiceTicket" else="viewGenericLoginSuccess" />
	</decision-state>
  • Componente executivo
    <action-state id="redirect">
        <evaluate expression="flowScope.service.getResponse(requestScope.serviceTicketId)" result-type="org.jasig.cas.authentication.principal.Response" result="requestScope.response" />
        <transition to="postRedirectDecision" />
    </action-state>

Leitura estendida: https://www.cnblogs.com/shuyuq/p/9729791.html

2. Saia e redirecione o posicionamento da chave

A propósito, o Sr. Zihan gostaria de compartilhar com você alguma experiência na leitura de código-fonte ~
Em circunstâncias normais, às vezes não conseguimos encontrar o local de entrada do código-fonte de empresas relacionadas de uma vez. Podemos
1. Podemos localizar o código-chave primeiro e depois usar a ordem inversa para ler.
2. Em seguida, leia o princípio do código-fonte e entenda profundamente seu processo de execução por meio da configuração de sequência positiva.

Ao analisar o código-fonte aqui, nós o lemos na ordem inversa.

  • Encontre o código-fonte redirecionado para a localização do url externo
	<!-- 
		The "redirect" end state allows CAS to properly end the workflow while still redirecting
		the user back to the service required.
	-->
	<end-state id="redirectView" view="externalRedirect:#{requestScope.response.url}" />
  • Encontre a etapa anterior
<!--检查cas管理的service范围,成功时支持重定向-->
    <action-state id="gatewayServicesManagementCheck">
        <evaluate expression="gatewayServicesManagementCheck" />
        <transition on="success" to="redirect" />
    </action-state>
<!--重定向事件执行,post请求时返回post结果 -->
    <action-state id="redirect">
        <evaluate expression="flowScope.service.getResponse(requestScope.serviceTicketId)" result-type="org.jasig.cas.authentication.principal.Response" result="requestScope.response" />
        <transition to="postRedirectDecision" />
    </action-state>
    <decision-state id="postRedirectDecision">
        <if test="requestScope.response.responseType.name() == 'POST'" then="postView" else="redirectView" />
    </decision-state>

gatewayServicesManagementCheckÉ um bean responsável pela detecção de serviço e gerenciado pelo Spring.

    <bean id="gatewayServicesManagementCheck" class="org.jasig.cas.web.flow.GatewayServicesManagementCheck"
          c:servicesManager-ref="servicesManager"/>

Veja o código-fonte:
org.jasig.cas.web.flow.GatewayServicesManagementCheck

public class GatewayServicesManagementCheck extends AbstractAction {
    
    

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @NotNull
    private final ServicesManager servicesManager;

    /**
     * Initialize the component with an instance of the services manager.
     * @param servicesManager the service registry instance.
     */
    public GatewayServicesManagementCheck(final ServicesManager servicesManager) {
    
    
        this.servicesManager = servicesManager;
    }

    @Override
    protected Event doExecute(final RequestContext context) throws Exception {
    
    
        final Service service = WebUtils.getService(context);

        final boolean match = this.servicesManager.matchesExistingService(service);

        if (match) {
    
    
            return success();
        }

        final String msg = String.format("ServiceManagement: Unauthorized Service Access. "
                + "Service [%s] does not match entries in service registry.", service.getId());
        logger.warn(msg);
        throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
    }
}

3. Olhe para o processo de saída do CAS novamente

3-1 Entrada de processo

O logout-webflow.xml define o método de saída baseado em url:

<!-- 通过后端触发的退出 -->
  <action-state id="doLogout">
    <evaluate expression="logoutAction" />
    <transition on="finish" to="finishLogout" />
    <transition on="front" to="frontLogout" />
  </action-state>

3-2 Sair da execução

Cas dá a ação de saída para o logoutActionBean, e os followServiceRedirectsparâmetros no Bean definem o intervalo de endereço URL de logout de redirecionamento:

    <!--  退出功能控制器,前端带你退出走这个action  -->
    <bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction"
          p:servicesManager-ref="servicesManager"
          p:followServiceRedirects="${cas.logout.followServiceRedirects:false}"/>

O logoutActioncódigo-fonte:

/**
 * Action to delete the TGT and the appropriate cookies.
 * It also performs the back-channel SLO on the services accessed by the user during its browsing.
 * After this back-channel SLO, a front-channel SLO can be started if some services require it.
 * The final logout page or a redirection url is also computed in this action.
 *
 * @author Scott Battaglia
 * @author Jerome Leleu
 * @since 3.0
 */
public final class LogoutAction extends AbstractLogoutAction {
    
    

    /** The services manager. */
    @NotNull
    private ServicesManager servicesManager;

    /**
     * Boolean to determine if we will redirect to any url provided in the
     * service request parameter.
     */
    private boolean followServiceRedirects;

    @Override
    protected Event doInternalExecute(final HttpServletRequest request, final HttpServletResponse response,
            final RequestContext context) throws Exception {
    
    

        boolean needFrontSlo = false;
        putLogoutIndex(context, 0);
        final List<LogoutRequest> logoutRequests = WebUtils.getLogoutRequests(context);
        if (logoutRequests != null) {
    
    
            for (LogoutRequest logoutRequest : logoutRequests) {
    
    
                // if some logout request must still be attempted
                if (logoutRequest.getStatus() == LogoutRequestStatus.NOT_ATTEMPTED) {
    
    
                    needFrontSlo = true;
                    break;
                }
            }
        }
		//==========小哥哥、小姐姐们,看这里~ start===============
        final String service = request.getParameter("service");
        if (this.followServiceRedirects && service != null) {
    
    
            final RegisteredService rService = this.servicesManager.findServiceBy(new SimpleWebApplicationServiceImpl(service));

            if (rService != null && rService.isEnabled()) {
    
    
                context.getFlowScope().put("logoutRedirectUrl", service);
            }
        }
   		//==========小哥哥、小姐姐们,看这里~ end===============

        // there are some front services to logout, perform front SLO
        //匹配到cas管理的service范围,退出后跳转到对应的service地址。
        if (needFrontSlo) {
    
    
            return new Event(this, FRONT_EVENT);
        } else {
    
    
            // otherwise, finish the logout process
            //否则,退出到cas默认的退出地址
            return new Event(this, FINISH_EVENT);
        }
    }

    public void setFollowServiceRedirects(final boolean followServiceRedirects) {
    
    
        this.followServiceRedirects = followServiceRedirects;
    }

    public void setServicesManager(final ServicesManager servicesManager) {
    
    
        this.servicesManager = servicesManager;
    }
}

3-3 Redirecionamento de serviço

  • Encontre o serviço correspondente e devolva :,
    context.getFlowScope().put("logoutRedirectUrl", service);dê-o afinishLogout
  <decision-state id="finishLogout">
    <if test="flowScope.logoutRedirectUrl != null" then="redirectView" else="logoutView" />
  </decision-state>
  • Caso contrário, saia para o endereço de logout padrão

Obrigado pela sua apreciação, oficial convidado, por favor clique em curtir e saia ~

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/l714417743/article/details/106494914
Recomendado
Clasificación