1、各framework版本信息
JDK 8
Tomcat 7
SpringMVC-4.2.0.RELEASE
Spring Security 4.2.0.RELEASE
CAS-Client 3.3.3
CAS-Server 4.0.0
2、MAVEN的pom.xml
影音先锋电影 http://www.iskdy.com/
3、配置CAS-Server
1)、下载CAS-Server的Zip包[http://developer.jasig.org/cas/]
解压后将modules文件夹中的[cas-server-webapp-4.0.0.war]放到tomcat的webapps文件夹中、重命名为cas.war。
启动tomcat、解压war包、浏览器中输入[http://localhost:8080/cas/]
打开CAS-Server的登录画面、输入默认用户名/密码:[casuser/Mellon]、提示[login success]即登录成功。
2)、修改CAS-Server配置文件、支持数据库登录校验
打开[../tomcat/webapps/cas/WEB-INF/deployerConfigContext.xml]文件
完成的配置文件
伦理片 http://www.dotdy.com/
同时需要将[c3p0-0.9.1.2.jar]、[cas-server-support-jdbc-4.0.0.jar](CAS-Servier的module目录中)、[mysql-connector-java-5.x.xx-bin.jar]放入[WEB-INF/lib]目录中。重新启动Tomcat、打开CAS登录画面验证是否可以进行数据库校验。
注意:1、修改配置文件中的sql文匹配自己的数据库。
2、密码列采用MD5加密、注意数据匹配
4、配置CAS-Client
1)、web.xml的配置
JDK 8
Tomcat 7
SpringMVC-4.2.0.RELEASE
Spring Security 4.2.0.RELEASE
CAS-Client 3.3.3
CAS-Server 4.0.0
2、MAVEN的pom.xml
- <!--Spring -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-orm</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-expression</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-instrument</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-instrument-tomcat</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc-portlet</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- <version>${spring.security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- <version>${spring.security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-cas</artifactId>
- <version>${spring.security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.jasig.cas.client</groupId>
- <artifactId>cas-client-core</artifactId>
- <version>3.3.3</version>
- <!-- 排除log4j包冲突 -->
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
影音先锋电影 http://www.iskdy.com/
3、配置CAS-Server
1)、下载CAS-Server的Zip包[http://developer.jasig.org/cas/]
解压后将modules文件夹中的[cas-server-webapp-4.0.0.war]放到tomcat的webapps文件夹中、重命名为cas.war。
启动tomcat、解压war包、浏览器中输入[http://localhost:8080/cas/]
打开CAS-Server的登录画面、输入默认用户名/密码:[casuser/Mellon]、提示[login success]即登录成功。
2)、修改CAS-Server配置文件、支持数据库登录校验
打开[../tomcat/webapps/cas/WEB-INF/deployerConfigContext.xml]文件
完成的配置文件
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- Licensed to Jasig under one or more contributor license
- agreements. See the NOTICE file distributed with this work
- for additional information regarding copyright ownership.
- Jasig licenses this file to you under the Apache License,
- Version 2.0 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a
- copy of the License at the following location:
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- -->
- <!--
- | deployerConfigContext.xml centralizes into one file some of the declarative configuration that
- | all CAS deployers will need to modify.
- |
- | This file declares some of the Spring-managed JavaBeans that make up a CAS deployment.
- | The beans declared in this file are instantiated at context initialization time by the Spring
- | ContextLoaderListener declared in web.xml. It finds this file because this
- | file is among those declared in the context parameter "contextConfigLocation".
- |
- | By far the most common change you will need to make in this file is to change the last bean
- | declaration to replace the default authentication handler with
- | one implementing your approach for authenticating usernames and passwords.
- +-->
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:c="http://www.springframework.org/schema/c"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:sec="http://www.springframework.org/schema/security"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
- <!--
- | The authentication manager defines security policy for authentication by specifying at a minimum
- | the authentication handlers that will be used to authenticate credential. While the AuthenticationManager
- | interface supports plugging in another implementation, the default PolicyBasedAuthenticationManager should
- | be sufficient in most cases.
- +-->
- <bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
- <constructor-arg>
- <map>
- <!--
- | IMPORTANT
- | Every handler requires a unique name.
- | If more than one instance of the same handler class is configured, you must explicitly
- | set its name to something other than its default name (typically the simple class name).
- -->
- <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
- <!-- <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />-->
- <entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver"/>
- </map>
- </constructor-arg>
- <!-- Uncomment the metadata populator to allow clearpass to capture and cache the password
- This switch effectively will turn on clearpass.
- <property name="authenticationMetaDataPopulators">
- <util:list>
- <bean class="org.jasig.cas.extension.clearpass.CacheCredentialsMetaDataPopulator"
- c:credentialCache-ref="encryptedMap" />
- </util:list>
- </property>
- -->
- <!--
- | Defines the security policy around authentication. Some alternative policies that ship with CAS:
- |
- | * NotPreventedAuthenticationPolicy - all credential must either pass or fail authentication
- | * AllAuthenticationPolicy - all presented credential must be authenticated successfully
- | * RequiredHandlerAuthenticationPolicy - specifies a handler that must authenticate its credential to pass
- -->
- <property name="authenticationPolicy">
- <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />
- </property>
- </bean>
- <!-- Required for proxy ticket mechanism. -->
- <bean id="proxyAuthenticationHandler"
- class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
- p:httpClient-ref="httpClient" />
- <!--
- | TODO: Replace this component with one suitable for your enviroment.
- |
- | This component provides authentication for the kind of credential used in your environment. In most cases
- | credential is a username/password pair that lives in a system of record like an LDAP directory.
- | The most common authentication handler beans:
- |
- | * org.jasig.cas.authentication.LdapAuthenticationHandler
- | * org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler
- | * org.jasig.cas.adaptors.x509.authentication.handler.support.X509CredentialsAuthenticationHandler
- | * org.jasig.cas.support.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler
- -->
- <bean id="primaryAuthenticationHandler"
- class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
- <property name="users">
- <map>
- <entry key="casuser" value="Mellon"/>
- </map>
- </property>
- </bean>
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
- p:driverClass="com.mysql.jdbc.Driver"
- p:jdbcUrl="jdbc:mysql://11.11.11.118:28306/flow?characterEncoding=utf8"
- p:user="root"
- p:password="root" />
- <bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
- c:encodingAlgorithm="MD5"
- p:characterEncoding="UTF-8" />
- <bean id="dbAuthHandler"
- class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"
- p:dataSource-ref="dataSource"
- p:sql="select password from user where name = ?"
- p:passwordEncoder-ref="passwordEncoder"/>
- <!-- p:passwordEncoder-ref="passwordEncoder" --><!-- 暂时不使用密码加密 -->
- <!-- Required for proxy ticket mechanism -->
- <bean id="proxyPrincipalResolver"
- class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />
- <!--
- | Resolves a principal from a credential using an attribute repository that is configured to resolve
- | against a deployer-specific store (e.g. LDAP).
- -->
- <bean id="primaryPrincipalResolver"
- class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
- <property name="attributeRepository" ref="attributeRepository" />
- </bean>
- <!--
- Bean that defines the attributes that a service may return. This example uses the Stub/Mock version. A real implementation
- may go against a database or LDAP server. The id should remain "attributeRepository" though.
- +-->
- <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
- p:backingMap-ref="attrRepoBackingMap" />
- <util:map id="attrRepoBackingMap">
- <entry key="uid" value="uid" />
- <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
- <entry key="groupMembership" value="groupMembership" />
- </util:map>
- <!--
- Sample, in-memory data store for the ServiceRegistry. A real implementation
- would probably want to replace this with the JPA-backed ServiceRegistry DAO
- The name of this bean should remain "serviceRegistryDao".
- +-->
- <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"
- p:registeredServices-ref="registeredServicesList" />
- <util:list id="registeredServicesList">
- <bean class="org.jasig.cas.services.RegexRegisteredService"
- p:id="0" p:name="HTTP and IMAP" p:description="Allows HTTP(S) and IMAP(S) protocols"
- p:serviceId="^(https?|imaps?)://.*" p:evaluationOrder="10000001" />
- <!--
- Use the following definition instead of the above to further restrict access
- to services within your domain (including sub domains).
- Note that example.com must be replaced with the domain you wish to permit.
- This example also demonstrates the configuration of an attribute filter
- that only allows for attributes whose length is 3.
- -->
- <!--
- <bean class="org.jasig.cas.services.RegexRegisteredService">
- <property name="id" value="1" />
- <property name="name" value="HTTP and IMAP on example.com" />
- <property name="description" value="Allows HTTP(S) and IMAP(S) protocols on example.com" />
- <property name="serviceId" value="^(https?|imaps?)://([A-Za-z0-9_-]+\.)*example\.com/.*" />
- <property name="evaluationOrder" value="0" />
- <property name="attributeFilter">
- <bean class="org.jasig.cas.services.support.RegisteredServiceRegexAttributeFilter" c:regex="^\w{3}$" />
- </property>
- </bean>
- -->
- </util:list>
- <bean id="auditTrailManager" class="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" />
- <bean id="healthCheckMonitor" class="org.jasig.cas.monitor.HealthCheckMonitor" p:monitors-ref="monitorsList" />
- <util:list id="monitorsList">
- <bean class="org.jasig.cas.monitor.MemoryMonitor" p:freeMemoryWarnThreshold="10" />
- <!--
- NOTE
- The following ticket registries support SessionMonitor:
- * DefaultTicketRegistry
- * JpaTicketRegistry
- Remove this monitor if you use an unsupported registry.
- -->
- <bean class="org.jasig.cas.monitor.SessionMonitor"
- p:ticketRegistry-ref="ticketRegistry"
- p:serviceTicketCountWarnThreshold="5000"
- p:sessionCountWarnThreshold="100000" />
- </util:list>
- </beans>
-
同时需要将[c3p0-0.9.1.2.jar]、[cas-server-support-jdbc-4.0.0.jar](CAS-Servier的module目录中)、[mysql-connector-java-5.x.xx-bin.jar]放入[WEB-INF/lib]目录中。重新启动Tomcat、打开CAS登录画面验证是否可以进行数据库校验。
注意:1、修改配置文件中的sql文匹配自己的数据库。
2、密码列采用MD5加密、注意数据匹配
4、配置CAS-Client
1)、web.xml的配置
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:/config/spring/spring.xml, classpath:/config/spring/spring-cas.xml</param-value>
- </context-param>
- <filter>
- <filter-name>CAS Single Sign Out Filter</filter-name>
- <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>CAS Single Sign Out Filter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <!--
- - Loads the root application context of this web app at startup.
- - The application context is then available via
- - WebApplicationContextUtils.getWebApplicationContext(servletContext).-->
- <listener>
- <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
- </listener>
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:sec="http://www.springframework.org/schema/security"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.2.xsd
-
2)、完整的spring-cas.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- http://www.springframework.org/schema/security/spring-security-4.0.xsd"
- default-lazy-init="true">
- <!-- 浏览权限设定,根据自己的情况修改 -->
- <sec:http auto-config="false" use-expressions="false" disable-url-rewriting="false"
- entry-point-ref="casProcessingFilterEntryPoint">
- <sec:headers disabled="true"/>
- <sec:csrf disabled="false"/>
- <sec:intercept-url pattern="/static/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
- <sec:intercept-url pattern="/**" access="ROLE_USER"/>
- <sec:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
- <sec:logout logout-success-url="/static/html/logout-success.html"/>
- <sec:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
- <sec:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
- </sec:http>
- <!-- This filter handles a Single Logout Request from the CAS Server -->
- <bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
- <!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
- <bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
- <constructor-arg value="http://localhost:8081/cas/logout"/>
- <constructor-arg>
- <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
- </constructor-arg>
- <property name="filterProcessesUrl" value="/logout/cas"/>
- </bean>
- <sec:authentication-manager alias="authenticationManager">
- <sec:authentication-provider ref="casAuthenticationProvider"/>
- </sec:authentication-manager>
- <bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"/>
- <!-- 认证失败返回的页面(非403错误)
- <property name="authenticationFailureHandler">
- <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
- <property name="defaultFailureUrl" value="/static/html/errors/403.html"/>
- </bean>
- </property>-->
- <!-- 认证成功返回的页面,此处做了修改,这个类是继续之前的操作。默认的类是设置一个固定的页面
- <property name="authenticationSuccessHandler">
- <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"/>
- </property>-->
- </bean>
- <bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
- <!-- 单点登录服务器登录URL -->
- <property name="loginUrl" value="http://localhost:8081/cas/login"/>
- <property name="serviceProperties" ref="serviceProperties"/>
- </bean>
- <bean id="userDetailsManager" class="cn.co.xxx.xxxx.xxxx.xxxx.x.UserDetailsManager"/>
- <bean id="casAuthenticationProvider"
- class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
- <property name="authenticationUserDetailsService">
- <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
- <constructor-arg ref="userDetailsManager" />
- </bean>
- </property>
- <property name="serviceProperties" ref="serviceProperties"/>
- <property name="ticketValidator">
- <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
- <constructor-arg index="0" value="http://localhost:8081/cas"/>
- </bean>
- </property>
- <property name="key" value="an_id_for_this_auth_provider_only"/>
- </bean>
- <!--
- <security:user-service id="userService">
- <security:user name="joe" password="joe" authorities="ROLE_USER" />
- ...
- </security:user-service>
- -->
- <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
- <!--[login/cas]是Spring Security 4.0后修改的地址、跟3.X版本完全不同、请勿修改-->
- <property name="service" value="http://localhost:8080/workflow/login/cas"/>
- <property name="sendRenew" value="false"/>
- </bean>
- </beans>
3)、UserDetailsManager
- import cn.co.yxht.workflow.service.UserIdentityService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.core.userdetails.UserDetailsService;
- import org.springframework.security.core.userdetails.UsernameNotFoundException;
- import org.springframework.stereotype.Service;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
- /**
- * Created by liulijun on 15/10/2.
- */
- public class UserDetailsManager implements UserDetailsService {
- /**
- * 注入用户信息查询Service
- */
- @Autowired
- private UserIdentityService userIdentityService;
- /**
- * 此处的参数[loginId]为CAS登录画面输入的用户名
- */
- @Override
- public UserDetails loadUserByUsername(String loginId) throws UsernameNotFoundException {
- Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
- UserDetails userDetails = new UserDetails() {
- /**
- * Returns the authorities granted to the user. Cannot return <code>null</code>.
- *
- * @return the authorities, sorted by natural key (never <code>null</code>)
- */
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities() {
- SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
- auths.add(authority);
- return auths;
- }
- /**
- * Returns the password used to authenticate the user.
- *
- * @return the password
- */
- @Override
- public String getPassword() {
- return "11";
- }
- /**
- * Returns the username used to authenticate the user. Cannot return <code>null</code>
- * .
- *
- * @return the username (never <code>null</code>)
- */
- @Override
- public String getUsername() {
- return "1";
- }
- /**
- * Indicates whether the user's account has expired. An expired account cannot be
- * authenticated.
- *
- * @return <code>true</code> if the user's account is valid (ie non-expired),
- * <code>false</code> if no longer valid (ie expired)
- */
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
- /**
- * Indicates whether the user is locked or unlocked. A locked user cannot be
- * authenticated.
- *
- * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
- */
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
- /**
- * Indicates whether the user's credentials (password) has expired. Expired
- * credentials prevent authentication.
- *
- * @return <code>true</code> if the user's credentials are valid (ie non-expired),
- * <code>false</code> if no longer valid (ie expired)
- */
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
- /**
- * Indicates whether the user is enabled or disabled. A disabled user cannot be
- * authenticated.
- *
- * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
- */
- @Override
- public boolean isEnabled() {
- return true;
- }
- };
- return userDetails;
- }
- }
4)、logout地址