• 使用CAS实现单点登录功能


    单点登录

    简介

    • 单点登录(Single Sign On),简称 SSO
    • 简单来说,就是只要一次登录了某个子系统,就顺带登录了其他的子系统。
    • 其目的很简单,就是为了减少用户访问子系统的成本。

    CAS服务器部署

    上传tomcat服务器压缩到文件夹/usr/local/cas目录下,解压,修改tomcat文件夹名为tomcat

    mkdir /usr/local/cas
    cd /usr/local/cas
    

    修改tomcat配置文件的端口号

    <server port="8010" shutdown="SHUTDOWN">
    
    <Connector port="9100" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
    

    关闭tomcat服务器,把CAS的war包放入tomcat的webapps目录当中后再启动tomcat服务器 对war包时行解压

    关闭tomcat服务器后, 删除war包

    /usr/local/cas/tomcat/bin/shutdown.sh
    rm -rf /usr/local/cas/tomcat/webapps/cas.war
    

    监听启动

    tail -f /usr/local/cas/tomcat/logs/catalina.out
    

    启动tomcat服务器

    /usr/local/cas/tomcat/bin/startup.sh
    

    访问http://192.168.1.88:9100/cas/login

    输入用户名casuser 密码:Mellon

    CAS使用

    去除https认证与设置cookie


    //关闭tomcat
    /usr/local/cas/tomcat/bin/shutdown.sh
    
    //修改参数
    vi /usr/local/cas/tomcat/webapps/cas/WEB-INF/classes/services/HTTPSandIMAPS-10000001.json
    {
    	"@class" : "org.apereo.cas.services.RegexRegisteredservice",
    	"serviceId" : "^(https|http|imaps)://.*",
    	"name" : "HTTPS and IMAPS",
    	"id" : 10000001,
    	"description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
    	"evaluationorder" : 10000
    }
    
    
    
    //添加参数
    vi /usr/local/cas/tomcat/webapps/cas/WEB-INF/classes/application.properties
    cas.tgc.secure=false
    cas.serviceRegistry.initFromJson=true
    #配置允许登出后跳转到指定页面
    cas.logout.followServiceRedirects=true
    #跳转到指定页面需要的参数名为 service
    cas.logout.redirectParameter=service
    
    
    //重启tomcat
    /usr/local/cas/tomcat/bin/startup.sh
    

    用户名和密码

    数据源方法

    修改Mysql远程访问权限

    create user user_cas identified with mysql_native_password by '123456';
    grant all on *.* to 'user_cas'@'%';
    FLUSH PRIVILEGES;
    

    配置用户认证

    将用户认证配置cas.authn.accept.users=casuser::Mellon注释掉
    vi /usr/local/cas/tomcat/webapps/cas/WEB-INF/classes/application.properties
    #cas.authn.accept.users=casuser::Mellon
    #设置用户认证配置(根据实际情况配置数据源)
    cas.authn.jdbc.query[0].url=jdbc:mysql://192.168.1.2:3306/fmstore?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
    #根据实际情况配置
    cas.authn.jdbc.query[0].user=user_cas
    #根据实际情况配置
    cas.authn.jdbc.query[0].password=123456
    cas.authn.jdbc.query[0].sql=select * from tb_user where username= ?
    cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
    cas.authn.jdbc.query[0].fieldPassword=password
    cas.authn.jdbc.query[0].fieldExpired=expired
    #cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
    

    自定义登录页面

    添加主题名称

    • 在/usr/local/cas/tomcat/webapps/cas/WEB-INF/classes/service/HTTPSandIMAPS-10000001.json中添加"theme" : "mypage"

    放入静态资源文件

    • 把图片放到static/images当中
    • js放到static/js当中
    • css放到static/css当中

    创建mypage.properties文件

    ​ 在/usr/local/cas/tomcat/webapps/cas/WEB-INF/classes目录当中创建mypage.properties文件

    #原cas默认的css样式,如果更改了,某些页面样式将丢失
    
    cas.standard.css.file=/css/cas.css
    #自己的样式
    cas.page.login.css=/css/pages-login.css
    cas.webbase.css=/css/webbase.css
    
    cas.jquery.easing.min.js=/js/jquery.easing.min.js
    cas.jquery.min.js=/js/jquery.min.js
    cas.jquery.placeholder.min.js=/js/jquery.placeholder.min.js
    cas.login.js=/js/login.js
    cas.sui.min.js=/js/sui.min.js
    
    cas.qq.png = /images/img/qq.png
    cas.weixin.png = /images/img/weixin.png
    

    在/usr/local/cas/tomcat/webapps/cas/WEB-INF/classes/templates中创建文件夹mypage

    把页面放进去

    在application.properties当中添加主题

    • cas.theme.defaultThemeName=mypage

    用户服务添加CAS

    引入pom文件

    <!--spring-security-->
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-web</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-config</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-taglibs</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-cas</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.jasig.cas.client</groupId>
    	<artifactId>cas-client-core</artifactId>
    	<exclusions>
    		<exclusion>
    			<groupId>org.slf4j</groupId>
    			<artifactId>log4j-over-slf4j</artifactId>
    		</exclusion>
    	</exclusions>
    </dependency>
    <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
    <dependency>
    	<groupId>joda-time</groupId>
    	<artifactId>joda-time</artifactId>
    	<version>2.10</version>
    </dependency>
    

    在web.xml当中添加过滤器

    <!--SpringSecurity-->
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-security.xml</param-value>
      </context-param>
      <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
    
      <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    添加配置文件spring/spring-security.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    			 xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    			 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
    
    	<!-- 放行静态资源-->
    	<http pattern="/css/**" security="none"></http>
    	<http pattern="/img/**" security="none"></http>
    	<http pattern="/js/**" security="none"></http>
    	<http pattern="/plugins/**" security="none"></http>
    
    	<!--放行一些请求-->
    	<http pattern="/register.html" security="none"></http>
    	<http pattern="/user/add.do" security="none"></http>
    	<http pattern="/user/sendCode.do" security="none"></http>
    
    	<!--   entry-point-ref  入口点引用 -->
    	<http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
    		<!--配置拦截器, 拦截所有请求, 应该具有ROLE_USER的权限才可以访问我们系统-->
    		<intercept-url pattern="/**" access="ROLE_USER"/>
    		<csrf disabled="true"/>
    		<!-- custom-filter为过滤器,
                    position 表示将过滤器放在指定的位置上,
                    before表示放在指定位置之前,
                    after表示放在指定的位置之后
            -->
    		<custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />
    		<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
    		<custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
    	</http>
    
    	<!-- CAS入口点 开始 -->
    	<beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    		<!-- 单点登录服务器登录URL -->
    		<beans:property name="loginUrl" value="http://192.168.1.88:9100/cas/login"/>
    		<beans:property name="serviceProperties" ref="serviceProperties"/>
    	</beans:bean>
    	<beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
    		<!--service 配置自身工程的根地址+/login/cas   -->
    		<beans:property name="service" value="http://127.0.0.1:8086/login/cas"/>
    	</beans:bean>
    
    	<!-- 认证过滤器 开始 -->
    	<beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
    		<beans:property name="authenticationManager" ref="authenticationManager"/>
    	</beans:bean>
    	<!-- 认证管理器 -->
    	<authentication-manager alias="authenticationManager">
    		<authentication-provider  ref="casAuthenticationProvider"></authentication-provider>
    	</authentication-manager>
    	<!-- 认证提供者 -->
    	<beans:bean id="casAuthenticationProvider"
    				class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    		<beans:property name="authenticationUserDetailsService">
    			<beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    				<beans:constructor-arg ref="userDetailsService" />
    			</beans:bean>
    		</beans:property>
    		<beans:property name="serviceProperties" ref="serviceProperties"/>
    		<!-- ticketValidator 为票据验证器 -->
    		<beans:property name="ticketValidator">
    			<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
    				<beans:constructor-arg index="0" value="http://192.168.1.88:9100/cas"/>
    			</beans:bean>
    		</beans:property>
    		<beans:property name="key" value="an_id_for_this_auth_provider_only"/>
    	</beans:bean>
    	<!-- 认证类 -->
    	<beans:bean id="userDetailsService" class="com.itxk.core.service.UserDetailServiceImpl"/>
    
    
    	<!-- 单点登出  开始  -->
    	<beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
    	<!-- 经过此配置,当用户在地址栏输入本地工程 /logout/cas  -->
    	<beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    		<beans:constructor-arg value="http://192.168.1.88:9100/cas/logout?service=http://127.0.0.1:8086"/>
    		<beans:constructor-arg>
    			<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
    		</beans:constructor-arg>
    		<beans:property name="filterProcessesUrl" value="/logout/cas"/>
    	</beans:bean>
    
    </beans:beans>
    

    创建认证类

    /**
     * 自定义认证类:
     * 在之前这里负责用户名密码的校验工作, 并给给当前用户赋予对应的访问权限
     * 现在cas和springSecurity集成, 集成后, 用户名密码的校验工作交给cas完成, 所以能够进入到
     * 这里类的方法中的都是已经成功认证的用户, 这里只需要给登录过的用户赋予对应的访问权限就可以
     */
    public class UserDetailServiceImpl implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //创建权限集合
            List<GrantedAuthority> authorityList = new ArrayList<>();
            //向权限集合中加入访问权限
            authorityList.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new User(username, "", authorityList);
        }
    }
    

    前端工程添加CAS

    在web.xml当中添加过滤器

    <!--SpringSecurity-->
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-security.xml</param-value>
      </context-param>
      <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
    
      <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    添加配置文件spring/spring-security.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
                 xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
    
        <!-- 放行静态资源-->
        <http pattern="/css/**" security="none"></http>
        <http pattern="/img/**" security="none"></http>
        <http pattern="/js/**" security="none"></http>
        <http pattern="/plugins/**" security="none"></http>
    
        <!--放行一些请求-->
        <http pattern="/index.html" security="none"></http>
        <http pattern="/search.html" security="none"></http>
        <http pattern="/cart.html" security="none"></http>
    
        <!--   entry-point-ref  入口点引用 -->
        <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
            <!-- 匿名角色 IS_AUTHENTICATED_ANONYMOUSLY -->
            <intercept-url pattern="/cart/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"></intercept-url>
            <intercept-url pattern="/itemsearch/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"></intercept-url>
            <!--配置拦截器, 拦截所有请求, 应该具有ROLE_USER的权限才可以访问我们系统-->
            <intercept-url pattern="/**" access="ROLE_USER"/>
            <csrf disabled="true"/>
            <!-- custom-filter为过滤器,
            position 表示将过滤器放在指定的位置上,
            before表示放在指定位置之前  ,
            after表示放在指定的位置之后  -->
            <custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />
            <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
            <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
        </http>
    
        <!-- CAS入口点 开始 -->
        <beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
            <!-- 单点登录服务器登录URL -->
            <beans:property name="loginUrl" value="http://192.168.1.88:9100/cas/login"/>
            <beans:property name="serviceProperties" ref="serviceProperties"/>
        </beans:bean>
        <beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
            <!--service 配置自身工程的根地址+/login/cas   -->
            <beans:property name="service" value="http://127.0.0.1:8083/login/cas"/>
        </beans:bean>
    
        <!-- 认证过滤器 开始 -->
        <beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
            <beans:property name="authenticationManager" ref="authenticationManager"/>
        </beans:bean>
        <!-- 认证管理器 -->
        <authentication-manager alias="authenticationManager">
            <authentication-provider  ref="casAuthenticationProvider"></authentication-provider>
        </authentication-manager>
        <!-- 认证提供者 -->
        <beans:bean id="casAuthenticationProvider"
                    class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
            <beans:property name="authenticationUserDetailsService">
                <beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                    <beans:constructor-arg ref="userDetailsService" />
                </beans:bean>
            </beans:property>
            <beans:property name="serviceProperties" ref="serviceProperties"/>
            <!-- ticketValidator 为票据验证器 -->
            <beans:property name="ticketValidator">
                <beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                    <beans:constructor-arg index="0" value="http://192.168.1.88:9100/cas"/>
                </beans:bean>
            </beans:property>
            <beans:property name="key" value="an_id_for_this_auth_provider_only"/>
        </beans:bean>
        <!-- 认证类 -->
        <beans:bean id="userDetailsService" class="com.itxk.core.service.UserDetailServiceImpl"/>
    
    
        <!-- 单点登出  开始  -->
        <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
        <!-- 经过此配置,当用户在地址栏输入本地工程 /logout/cas  -->
        <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
            <beans:constructor-arg value="http://192.168.1.88:9100/cas/logout?service=http://127.0.0.1:8083"/>
            <beans:constructor-arg>
                <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
            </beans:constructor-arg>
            <beans:property name="filterProcessesUrl" value="/logout/cas"/>
        </beans:bean>
    
    </beans:beans>
    

    创建认证类

    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    
    import java.util.ArrayList;
    import java.util.List;
    /**
     * 自定义认证类:
     * 在之前这里负责用户名密码的校验工作, 并给给当前用户赋予对应的访问权限
     * 现在cas和springSecurity集成, 集成后, 用户名密码的校验工作交给cas完成, 所以能够进入到
     * 这里类的方法中的都是已经成功认证的用户, 这里只需要给登录过的用户赋予对应的访问权限就可以
     */
    public class UserDetailServiceImpl implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //创建权限集合
            List<GrantedAuthority> authorityList = new ArrayList<>();
            //向权限集合中加入访问权限
            authorityList.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new User(username, "", authorityList);
        }
    }
    

  • 相关阅读:
    JavaScript——标准对象
    JavaScript——方法
    JavaScript——变量作用域
    移动开发程序员的悲哀是什么?
    腾讯14年老员工被公司恶意逼走!以不胜任工作为由被裁!腾讯对待老员工也太狠了吧?
    Android开发北漂 8 年,飘飘飘 飘够了。。。。
    我是双非/三本/专科学校的Android开发,我有机会进入大厂吗?
    Android开发3年,我转Java后台了,真香!
    我的字节跳动Android面试初体验——稀里糊涂结束战斗
    Android Studio 教程:入门开发第一个程序
  • 原文地址:https://www.cnblogs.com/mumuyinxin/p/11713905.html
Copyright © 2020-2023  润新知