`
pengfeifei26
  • 浏览: 241213 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

让CAS支持客户端自定义登陆页面——服务器配置

    博客分类:
  • cas
 
阅读更多
1、修改/WEB-INF/web.xml,为cas增加一个/remoteLogin和//remoteLogout的映射,否则总是会转到login那个请求去了:
 <servlet-mapping>
     <servlet-name>cas</servlet-name>
     <url-pattern>/remoteLogin</url-pattern>
 </servlet-mapping>
 
 <servlet-mapping>
     <servlet-name>cas</servlet-name>
     <url-pattern>/remoteLogout</url-pattern>
 </servlet-mapping>
 



2、然后修改cas-servlet.xml文件,增加对/remoteLogin和/remoteLogout映射的处理,需要增加两个新流程:

<!-- 增加远程控制者,允许以/remote请求启动remote控制流程 -->
 
 <bean id="handlerMappingB" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">
         <props>
             <prop key="/remoteLogin">remoteLoginController</prop>
             <prop key="/remoteLogout">remoteLogoutController</prop>
         </props>
     </property>
     <property name="interceptors">
         <list>
             <ref bean="localeChangeInterceptor" />
         </list>
     </property>
 </bean>
 
 <bean id="remoteLoginController" class="org.springframework.webflow.mvc.servlet.FlowController">
  <property name="flowExecutor" ref="remoteLoginFlowExecutor" />
  <property name="flowUrlHandler" ref="flowUrlHandler"/>
 </bean>
        
 <webflow:flow-executor id="remoteLoginFlowExecutor" flow-registry="remoteLoginFlowRegistry">
     <webflow:flow-execution-attributes>
         <webflow:always-redirect-on-pause value="false"/>
     </webflow:flow-execution-attributes>
 </webflow:flow-executor>
 
 <webflow:flow-registry id="remoteLoginFlowRegistry" flow-builder-services="builder">
     <webflow:flow-location path="/WEB-INF/remoteLogin-webflow.xml" id="remoteLogin"/>
 </webflow:flow-registry>
 
 <webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator"/>
 
 <bean id="remoteLoginAction" class="com.cas.web.flow.RemoteLoginAction"
     p:argumentExtractors-ref="argumentExtractors"
  p:warnCookieGenerator-ref="warnCookieGenerator"
  p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator" />
  
 <bean id="remoteLogoutController" class="org.springframework.webflow.mvc.servlet.FlowController">
  <property name="flowExecutor" ref="remoteLogoutFlowExecutor" />
  <property name="flowUrlHandler" ref="flowUrlHandler"/>
 </bean>
 
 <webflow:flow-executor id="remoteLogoutFlowExecutor" flow-registry="remoteLogoutFlowRegistry">
     <webflow:flow-execution-attributes>
         <webflow:always-redirect-on-pause value="false"/>
     </webflow:flow-execution-attributes>
 </webflow:flow-executor>
 <webflow:flow-registry id="remoteLogoutFlowRegistry" flow-builder-services="builder">
     <webflow:flow-location path="/WEB-INF/remoteLogout-webflow.xml" id="remoteLogout"/>
 </webflow:flow-registry>
 
 <bean id="remoteLogoutAction" class="com.cas.web.flow.RemoteLogoutAction"
  p:argumentExtractors-ref="argumentExtractors"
  p:warnCookieGenerator-ref="warnCookieGenerator"
  p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"
     p:centralAuthenticationService-ref="centralAuthenticationService" />
 



3、流程定义的xml文件:可以看到上面将请求指向了webflow配置文件/WEB-INF/remoteLogin-webflow.xml和/WEB-INF/remoteLogout-webflow.xml,我们需要创建此文件并配置其成为我们所需的流程。

以下是remoteLogin-webflow.xml全文:
 
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
      start-state="remoteLogin">
    <!--
    <on-start>
        <evaluate expression="remoteLoginAction.doBind(flowRequestContext, flowScope.credentials)" />
    </on-start>
 
 -->
 <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
 <!-- 远程登陆主要Action -->
    <action-state id="remoteLogin">
        <evaluate expression="remoteLoginAction" />
        <transition on="error" to="remoteCallbackView" />
        <transition on="submit" to="bindAndValidate" />
        <transition on="checkTicketGrantingTicket" to="ticketGrantingTicketExistsCheck" />
    </action-state>
    
    <!-- 远程回调页面,主要以JavaScript的方式回传一些参数用 -->
    <end-state id="remoteCallbackView" view="remoteCallbackView" />
    
    <action-state id="bindAndValidate">
     <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
        <transition on="success" to="submit" />
        <transition on="error" to="remoteCallbackView" />
    </action-state>
    
    <decision-state id="ticketGrantingTicketExistsCheck">
  <if test="flowScope.ticketGrantingTicketId != null" then="hasServiceCheck" else="gatewayRequestCheck" />
 </decision-state>
 
 <decision-state id="hasServiceCheck">
        <if test="flowScope.service != null" then="generateServiceTicket" else="remoteCallbackView" />
    </decision-state>
 <decision-state id="gatewayRequestCheck">
  <if test="externalContext.requestParameterMap['gateway'] neq '' &amp;&amp; externalContext.requestParameterMap['gateway'] neq null &amp;&amp; flowScope.service neq null" then="redirect" else="remoteCallbackView" />
 </decision-state>
 
 <action-state id="generateServiceTicket">
        <evaluate expression="generateServiceTicketAction" />
        <transition on="success" to ="warn" />
        <transition on="error" to="remoteCallbackView" />
        <transition on="gateway" to="redirect" />
    </action-state>
 
 <decision-state id="warn">
  <if test="flowScope.warnCookieValue" then="showWarningView" else="redirect" />
 </decision-state>
 
 <action-state id="submit">
        <evaluate expression="authenticationViaFormAction.submit(flowRequestContext, messageContext)" />
  <transition on="warn" to="warn" />
  <transition on="success" to="sendTicketGrantingTicket" />
  <transition on="error" to="remoteCallbackView" />
 </action-state> 
 
 <action-state id="sendTicketGrantingTicket">
        <evaluate expression="sendTicketGrantingTicketAction" />
  <transition to="serviceCheck" />
 </action-state>
 
 <decision-state id="serviceCheck">
  <if test="flowScope.service neq null" then="generateServiceTicket" else="remoteCallbackView" />
 </decision-state>
    
 <end-state id="showWarningView" view="casLoginConfirmView" />
 
 <!--<end-state id="redirect" view="bean:dynamicRedirectViewSelector" />
 
 --><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() eq 'POST'" then="postView" else="redirectView" />
    </decision-state>
    <end-state id="postView" view="postResponseView">
        <on-entry>
            <set name="requestScope.parameters" value="requestScope.response.attributes" />
            <set name="requestScope.originalUrl" value="flowScope.service.id" />
        </on-entry>
    </end-state>
    <end-state id="redirectView" view="externalRedirect:${requestScope.response.url}" />
    
 <end-state id="viewServiceErrorView" view="viewServiceErrorView" />
 <end-state id="viewServiceSsoErrorView" view="viewServiceSsoErrorView" />
    
 <global-transitions>
        <transition to="viewServiceErrorView" on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" />
        <transition to="viewServiceSsoErrorView" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException" />
        <transition to="viewServiceErrorView" on-exception="org.jasig.cas.services.UnauthorizedServiceException" />
    </global-transitions>
</flow>
 
    


以下是remoteLogout-webflow.xml全文:
 
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
      start-state="remoteLogout">
 
 <!-- 远程登陆主要Action -->
    <action-state id="remoteLogout">
        <evaluate expression="remoteLogoutAction" />
        <transition on="success" to="remoteCallbackView" />
    </action-state>
    <end-state id="remoteCallbackView" view="remoteCallbackView" />
 <global-transitions>
        <transition to="viewServiceErrorView" on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" />
        <transition to="viewServiceSsoErrorView" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException" />
        <transition to="viewServiceErrorView" on-exception="org.jasig.cas.services.UnauthorizedServiceException" />
    </global-transitions>
</flow>
 



4、流程首先由Action类进行处理,成功或失败都将转回 remoteCallbackView,这样就返回了远程的登录页面。

4.1、登录处理Action类:
 
package com.cas.web.flow;
 
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
 
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.web.support.ArgumentExtractor;
import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;
import org.jasig.cas.web.support.WebUtils;
import org.springframework.util.StringUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
 
/**
* 远程登陆票据提供Action.
* 根据InitialFlowSetupAction修改.
* 由于InitialFlowSetupAction为final类,因此只能将代码复制过来再进行修改.
*/
public class RemoteLoginAction extends AbstractAction {
    /** CookieGenerator for the Warnings. */
    @NotNull
    private CookieRetrievingCookieGenerator warnCookieGenerator;
    /** CookieGenerator for the TicketGrantingTickets. */
    @NotNull
    private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
    /** Extractors for finding the service. */
    @NotNull
    @Size(min=1)
    private List<ArgumentExtractor> argumentExtractors;
    /** Boolean to note whether we've set the values on the generators or not. */
    private boolean pathPopulated = false;
    
    protected Event doExecute(final RequestContext context) throws Exception {
        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
        if (!this.pathPopulated) {
            final String contextPath = context.getExternalContext().getContextPath();
            final String cookiePath = StringUtils.hasText(contextPath) ? contextPath : "/";
            logger.info("Setting path for cookies to: " + cookiePath);
            this.warnCookieGenerator.setCookiePath(cookiePath);
            this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath);
            this.pathPopulated = true;
        }
        context.getFlowScope().put("ticketGrantingTicketId", this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));
        context.getFlowScope().put("warnCookieValue", Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request)));
        final Service service = WebUtils.getService(this.argumentExtractors, context);
        if (service != null && logger.isDebugEnabled()) {
            logger.debug("Placing service in FlowScope: " + service.getId());
        }
        context.getFlowScope().put("service", service);
        
        // 客户端必须传递loginUrl参数过来,否则无法确定登陆目标页面
        if (StringUtils.hasText(request.getParameter("loginUrl"))) {
            context.getFlowScope().put("remoteLoginUrl", request.getParameter("loginUrl"));
        } else {
            request.setAttribute("remoteLoginMessage", "loginUrl parameter must be supported.");
            return error();
        }
        
        // 若参数包含submit则进行提交,否则进行验证
        if (StringUtils.hasText(request.getParameter("submit"))) {
            return result("submit");
        } else {
            return result("checkTicketGrantingTicket");
        }
    }
    public void setTicketGrantingTicketCookieGenerator(
        final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator) {
        this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator;
    }
    public void setWarnCookieGenerator(final CookieRetrievingCookieGenerator warnCookieGenerator) {
        this.warnCookieGenerator = warnCookieGenerator;
    }
    public void setArgumentExtractors(final List<ArgumentExtractor> argumentExtractors) {
        this.argumentExtractors = argumentExtractors;
    }
}
 




4.2、退出处理Action类:
 
package com.cas.web.flow;
 
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
 
import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.web.support.ArgumentExtractor;
import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;
import org.jasig.cas.web.support.WebUtils;
import org.springframework.util.StringUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
 
public class RemoteLogoutAction extends AbstractAction {
 @NotNull
    private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
 @NotNull
    private CookieRetrievingCookieGenerator warnCookieGenerator;
 @NotNull
 private CentralAuthenticationService centralAuthenticationService;
 @NotNull
    @Size(min=1)
    private List<ArgumentExtractor> argumentExtractors;
 private boolean pathPopulated = false;
 @Override
 protected Event doExecute(final RequestContext context) throws Exception {
        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
        final HttpServletResponse response = WebUtils.getHttpServletResponse(context);
 
        if (!this.pathPopulated) {
            final String contextPath = context.getExternalContext().getContextPath();
            final String cookiePath = StringUtils.hasText(contextPath) ? contextPath : "/";
            logger.info("Setting path for cookies to: " + cookiePath);
            this.warnCookieGenerator.setCookiePath(cookiePath);
            this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath);
            this.pathPopulated = true;
        }
        context.getFlowScope().put("ticketGrantingTicketId", this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));
        context.getFlowScope().put("warnCookieValue", Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request)));
        final Service service = WebUtils.getService(this.argumentExtractors, context);
        if (service != null && logger.isDebugEnabled()) {
            logger.debug("Placing service in FlowScope: " + service.getId());
        }
        context.getFlowScope().put("service", service);
        context.getFlowScope().put("remoteLoginUrl", request.getParameter("service"));
        final String ticketGrantingTicketId = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request);
 
        if (ticketGrantingTicketId != null) {
            this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
 
            this.ticketGrantingTicketCookieGenerator.removeCookie(response);
            this.warnCookieGenerator.removeCookie(response);
        }
        
        return result("success");
 }
    public void setTicketGrantingTicketCookieGenerator(final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator) {
            this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator;
 }
 public void setWarnCookieGenerator(final CookieRetrievingCookieGenerator warnCookieGenerator) {
            this.warnCookieGenerator = warnCookieGenerator;
 }
 public void setArgumentExtractors(final List<ArgumentExtractor> argumentExtractors) {
            this.argumentExtractors = argumentExtractors;
 }
 public void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService){
  this.centralAuthenticationService = centralAuthenticationService;
 }
}


4.3、cas的登录页面,username和password是传递给

<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />

这个变量的,判断用户登录信息也以这个变量传递给org.jasig.cas.web.flow.AuthenticationViaFormAction的submit方法来进行,很遗憾,这个变量没法中间赋值(反正我不会),所以我重构了一个方法:
 
    public final String submit(final RequestContext context, final MessageContext messageContext) throws Exception {
        // Validate login ticket
        final String authoritativeLoginTicket = WebUtils.getLoginTicketFromFlowScope(context);
        final String providedLoginTicket = WebUtils.getLoginTicketFromRequest(context);
        if (!authoritativeLoginTicket.equals(providedLoginTicket)) {
            this.logger.warn("Invalid login ticket " + providedLoginTicket);
            final String code = "INVALID_TICKET";
            messageContext.addMessage(new MessageBuilder().error().code(code).arg(providedLoginTicket).defaultText(code).build());
            return "error";
        }
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        final Service service = WebUtils.getService(context);
        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
        org.jasig.cas.authentication.principal.UsernamePasswordCredentials credentials = new org.jasig.cas.authentication.principal.UsernamePasswordCredentials();
        credentials.setPassword(request.getParameter("password"));
        credentials.setUsername(request.getParameter("username"));
        if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) {
            try {
                final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);
                WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
                putWarnCookieIfRequestParameterPresent(context);
                return "warn";
            } catch (final TicketException e) {
                if (e.getCause() != null && AuthenticationException.class.isAssignableFrom(e.getCause().getClass())) {
                    populateErrorsInstance(e, messageContext);
                    return "error";
                }
                this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
                if (logger.isDebugEnabled()) {
                    logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);
                }
            }
        }
        try {
            WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
            putWarnCookieIfRequestParameterPresent(context);
            return "success";
        } catch (final TicketException e) {
            populateErrorsInstance(e, messageContext);
            return "error";
        }
    }
 

    这个方法直接从request里获得username和password,然后验证。

   

5、配置remoteCallbackView显示节点,修改src/default_views.properties文件,增加remoteCallbackView配置:

### 配置远程回调页面
remoteCallbackView.(class)=org.springframework.web.servlet.view.JstlView
remoteCallbackView.url=/WEB-INF/view/jsp/default/ui/remoteCallbackView.jsp



6、创建/WEB-INF/view/jsp/default/ui/remoteCallbackView.jsp文件:
 
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
    <script type="text/javascript">
        var remoteUrl = "${remoteLoginUrl}?validated=true";
        // 构造错误消息
        var errorMessage = "";
        <spring:hasBindErrors name="credentials">
         errorMessage = "&errorMessage=" + encodeURIComponent('<c:forEach var="error" items="${errors.allErrors}"><spring:message code="${error.code}" text="${error.defaultMessage}" /></c:forEach>');
        </spring:hasBindErrors>
        
        // 构造service
        var service = "";
        <c:if test="${service != null && service != ''}">
         service = "&service=" + encodeURIComponent("${service}");
        </c:if>
        // 跳转回去
        window.location.href = remoteUrl + errorMessage + service;
    </script>
</head>
<body>
    ${remoteLoginMessage}
</body>
</html>

CAS 之自定义登录页实践 http://denger.iteye.com/blog/809170
https://wiki.jasig.org/display/CAS/Using+CAS+without+the+Login+Screen
分享到:
评论

相关推荐

    让CAS支持客户端自定义登陆页面——服务器篇[参考].pdf

    "CAS支持客户端自定义登陆页面——服务器篇" 为了让CAS支持客户端自定义登陆页面,需要在服务器端进行修改。首先,需要在/WEB-INF/web.xml文件中增加一个/remoteLogin的映射,以便将请求指向新的登陆页面。其次,...

    让CAS支持客户端自定义登陆页面——客户端篇

    标题中的“让CAS支持客户端自定义登陆页面——客户端篇”表明了本文主要探讨的是如何在中央认证服务(Central Authentication Service, CAS)系统中,允许客户端应用程序实现自定义登录页面的配置与实现。...

    让CAS支持客户端自定义登陆页面——服务器篇.docx

    ### 让CAS支持客户端自定义登录页面——服务器篇 #### 概述 本文档主要介绍如何在CAS(Central Authentication Service)系统中实现客户端自定义登录页面的功能,并且着重讲解服务器端的修改步骤与注意事项。CAS...

    让CAS支持客户端自定义登陆页面----服务器篇--.doc

    【让CAS支持客户端自定义登陆页面——服务器篇】 CAS(Central Authentication Service)是一个开源的身份验证框架,它允许用户通过单一登录(Single Sign-On, SSO)访问多个应用系统。在某些场景下,用户可能希望...

    CAS客户端开发配置及其所需求的最基本的jar文件

    在开发CAS客户端时,确保客户端正确配置并与CAS服务器通信至关重要,以解决“即将定向不安全的连接”这类问题。 首先,理解CAS的基本工作原理:用户尝试访问受保护的资源时,会被重定向到CAS服务器进行身份验证。...

    JASIG CAS 3 Learning Note 1 -- getting started

    例如,你可以设置 CAS 服务器的端口号、服务验证的URL以及支持的认证协议。 接下来,为了实现单点登录,你需要在你的应用系统(客户端)中集成 CAS。这通常包括以下几个步骤: 1. **配置 CAS 客户端库**:在你的...

    cas server

    3. **部署与配置**:安装CAS Server通常涉及下载CAS服务器的最新稳定版本(如cas-3.5.3),配置服务器环境,比如Java运行时环境(JRE或JDK)、Tomcat或其他Servlet容器,以及修改相应的配置文件以适应组织的特定需求...

    基于Java的源码-单点登录系统 JA-SIG CAS.zip

    此外,CAS支持Spring框架,可以轻松地在Spring环境中配置和使用。 **关键技术** 1. **Servlets**:用于处理HTTP请求。 2. **JSP**:用于生成动态页面内容。 3. **Java Authentication and Authorization Service ...

    spring security2 安全手册(牛人写的)

    - **修改配置文件**:更新Spring Security配置以支持自定义登录页面。 - **登录页面中的参数配置**:设置登录表单所需的参数,如用户名和密码字段名称等。 - **测试一下**:验证自定义登录页面的功能是否正常工作。 ...

    spring security

    - **为 jetty 配置 Realm**: 配置 Jetty 服务器支持预先认证。 - **配置 Spring Security**: 在 Spring Security 中启用预先认证功能。 ##### 18. 切换用户 - **配置方式**: 配置切换用户功能。 - **实例演示**: ...

    PyPI 官网下载 | ftw.casauth-1.4.1.tar.gz

    1. CAS客户端支持:它实现了与CAS服务器的通信,包括票证验证、登录和登出操作。 2. 集成简单:该库易于集成到基于Python的Web应用程序中,如Flask和Django,通过提供中间件或装饰器,可以方便地添加CAS身份验证。 3...

    SpringSecurity 3.0.1.RELEASE.CHM

    21.3. 配置CAS客户端 22. X.509认证 22.1. 概述 22.2. 把X.509认证添加到你的web系统中 22.3. 为tomcat配置SSL 23. 替换验证身份 23.1. 概述 23.2. 配置 A. 安全数据库表结构 A.1. User表 A.1.1. 组权限 ...

    JAVA上百实例源码以及开源项目源代码

    多人聊天室 3个目标文件 第一步:运行ServerData.java 启动服务器,然后服务器处于等待状态 第二步:运行LoginData.java 启动(客户端)登陆界面 输入用户名 ip为本机localhost 第三步:在登陆后的界面文本框输入文本...

Global site tag (gtag.js) - Google Analytics