單點登陸(SSO)解決方案之 CAS客戶端與Spring Security集成

接上篇:單點登陸(SSO)解決方案之 CAS服務端數據源設置及頁面改造html

Spring Security

  Spring Security是一個可以爲基於Spring的企業應用系統提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組能夠在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,爲應用系統提供聲明式的安全訪問控制功能,減小了爲企業系統安全控制編寫大量重複代碼的工做。java

爲何使用CAS集成Spring Security?

  首先咱們要明白,一個系統都須要有認證和受權的過程:web

    所謂認證,就是當用戶試圖進入系統,而系統發現用戶沒有登錄,就調轉到登錄頁面,而後用戶輸入用戶名,密碼,點擊登錄按鈕,系統進行用戶名,密碼的校驗過程,稱之爲認證。
    所謂受權,指的是系統對用戶名,密碼進行認證經過,而後對該用戶賦權限,即該用戶可以訪問這個系統的哪些功能(即該用戶可以訪問這個系統的哪些url地址及按鈕)。spring

  Spring Security自己是具備認證功能的,可是咱們使用CAS作單點登陸就至關於把認證這一部分放在了CAS上,也就是說咱們使用CAS作認證。數據庫

  咱們大部分的系統都會有用戶、角色以及權限表,咱們在CAS作過認證之後使用Spring Security進行受權,也就是認證過的用戶取出該用戶的權限,根據權限來控制該用戶能訪問哪些頁面等。express

 

CAS客戶端與Spring Security集成Demo:

1,搭建客戶端casclient_demo3,引入spring依賴和spring secrity 相關依賴 ,tomcat端口設置爲9003apache

pom.xml編程

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>project_demo</artifactId>
        <groupId>com.zy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>casclient_demo3</artifactId>
    <packaging>war</packaging>

    <properties>
        <spring.version>4.2.4.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</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-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--security-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.1.0.RELEASE</version>
        </dependency>

        <!--servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <!--spring和cas集成須要的兩個jar包-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
            <version>4.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.jasig.cas.client</groupId>
            <artifactId>cas-client-core</artifactId>
            <version>3.3.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <!-- java編譯插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定端口 -->
                    <port>9003</port>
                    <!-- 請求路徑 -->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

2,修改web.xml ,添加過濾器等配置api

web.xml瀏覽器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-security.xml</param-value>
    </context-param>
    <listener>
        <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
    </listener>

    <!--security過濾器鏈-->
    <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>


    <!--springMVC DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定加載的配置文件 ,經過參數contextConfigLocation加載-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

 

3,建立配置文件springmvc.xml及spring-security.xml

resources/springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.zy.demo.controller"/>

    <mvc:annotation-driven/>

</beans>

resources/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">


    <!--攔截規則 entry-point-ref爲入口點引用 use-expressions默認是true -->
    <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
        <!--容許匿名訪問的鏈接地址-->
        <intercept-url pattern="/public/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"></intercept-url>
        <!-- /* 當前級別目標 子目錄是不攔截-->
        <!--若是是ROLE_ADMIN則不攔截admin文件夾下的-->
        <intercept-url pattern="/admin/**" access="ROLE_ADMIN"></intercept-url>
        <!--若是是ROLE_LEADER則不攔截leader文件夾下的-->
        <intercept-url pattern="/leader/**" access="ROLE_LEADER"></intercept-url>
        <!--若是兩個角色都有 全部的都不攔截-->
        <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_LEADER"></intercept-url>
        <!--關閉防CSRF攻擊-->
        <csrf disabled="true"></csrf>

        <!--配置認證過濾器-->
        <!-- 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://localhost:9100/cas/login"/>-->
        <beans:property name="loginUrl" value="http://192.168.44.31: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://localhost:9003/login/cas"/>
    </beans:bean>
    <!-- CAS入口點 結束 -->


    <!-- 認證過濾器 開始 -->
    <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://localhost:9100/cas"/>-->
                <beans:constructor-arg index="0" value="http://192.168.44.31:9100/cas"/>
            </beans:bean>
        </beans:property>
        <beans:property name="key" value="an_id_for_this_auth_provider_only"/>
    </beans:bean>

    <!--獲取受權信息的bean-->
    <!-- 認證類 -->
    <beans:bean id="userDetailsService" class="com.zy.demo.service.UserDetailsServiceImpl"/>
    <!-- 認證過濾器 結束 -->


    <!--退出的過濾器-->
    <!-- 單點登出 開始 -->
    <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
    <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <!--退出登陸後跳轉到百度-->
        <!--<beans:constructor-arg value="http://localhost:9100/cas/logout?service=http://www.baidu.com"/>-->
        <beans:constructor-arg value="http://192.168.44.31:9100/cas/logout?service=http://www.baidu.com"/>
        <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>

 

4,編寫認證類java.com.zy.demo.controller.service.UserDetailsServiceImpl  須要實現UserDetailsService接口

package com.zy.demo.service; 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 org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * 使用security控制權限 */ @Component public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //能夠根據用戶名取數據庫取出來權限
        String authorityLeader = "ROLE_LEADER"; String authorityAdmin = "ROLE_ADMIN"; //而後受權
        List<GrantedAuthority> authorityList = new ArrayList<>();//權限列表 //GrantedAuthority authority = new SimpleGrantedAuthority(authorityLeader);//權限
        authorityList.add(new SimpleGrantedAuthority(authorityLeader)); //authorityList.add(new SimpleGrantedAuthority(authorityAdmin));
 System.out.println("對用戶進行受權"); return new User(username, "", authorityList); } }

 

5,添加測試html頁面

在webapp下新建leader和admin兩個文件夾,並在文件夾內分別新建index.jsp頁面(當前頁能夠建其餘頁面,此處主要用來演示權限限制):

webapp/admin/index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>admin頁面</h1>
<%=request.getRemoteUser()%>
<br/>
<a href="/logout/cas">單點退出</a>
</body>
</html>

webapp/leader/index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>leader頁面</h1>
<%=request.getRemoteUser()%>
<br/>
<a href="/logout/cas">單點退出</a>
</body>
</html>

以上工程搭建完成。

 

啓動項目,瀏覽器輸入localhost:9003/leader/index.jsp,登陸後:

 

瀏覽器輸入localhost:9003/admin/index.jsp:

拒絕訪問,由於咱們在UserDetailsServiceImpl 只給用戶賦予了ROLE_LEADER的權限。

 

以上。

 

後續補充:Demo及所需資料百度雲地址:連接:https://pan.baidu.com/s/1Dr4Aq9-FWGnL3kRCZ3uwVA 密碼:0i30

相關文章
相關標籤/搜索