单点登录:spring-security-cas

  单点登录Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统

Centos7安装cas系统

  (1) 上传cas.war到Centos机器的tomcat/webapps目录下

  (2) 端口修改

vim /usr/local/tomcat/apache-tomcat-7.0.52/conf/web.xml

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/cas.properties

   (3) 去除https认证

    1) 修改casWEB-INF/deployerConfigContext.xml

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/deployerConfigContext.xml

    2) 修改cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml

    参数p:cookieSecure="true",同理为HTTPS验证相关,TRUE为采用HTTPS验证,FALSE为不采用https验证。

    参数p:cookieMaxAge="-1",是COOKIE的最大生命周期,-1为无生命周期,即只在当前打开的窗口有效,关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0的数字,比如3600等,意思是在3600秒内,打开任意窗口,都不需要验证

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml 

    3) 修改casWEB-INF/spring-configuration/warnCookieGenerator.xml

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/spring-configuration/warnCookieGenerator.xml

  (4) cas认证数据源配置

    1) 修改cas服务端中web-infdeployerConfigContext.xml ,添加如下配置

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  
              p:driverClass="com.mysql.jdbc.Driver"  
              p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/db?characterEncoding=utf8"  
              p:user="user"  
              p:password="password" /> 
<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 tb_user where username = ?"  
          p:passwordEncoder-ref="passwordEncoder"/>

    2)

注释:<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
添加:<entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver"/>
搜索定位:在浏览模式下:/<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />

    3) 导入jar包

cp -r c3p0-0.9.1.2.jar /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/lib
cp -r cas-server-support-jdbc-4.0.0.jar /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/lib
cp -r mysql-connector-java-5.1.32.jar /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/lib

   (5) 替换cas登录页面

    1) 将css  js等文件夹拷贝到  cas目录下

    2) 将工程登录页拷贝到cas系统下WEB-INF\view\jsp\default\ui 目录下,并重命名为casLoginView.jsp(先重命名cas系统原casLoginView.jsp)

    3) 添加指令

<%@ page pageEncoding="UTF-8" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

    4) 修改form标签

<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true" class="sui-form">
......
</form:form>

    5) 修改登录框

<form:input id="username" tabindex="1" 
    accesskey="${userNameAccessKey}" path="username" autocomplete="off" htmlEscape="true" 
    placeholder="邮箱/用户名/手机号" class="span2 input-xfat" />
<form:password  id="password" tabindex="2" path="password" 
      accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" 
      placeholder="请输入密码" class="span2 input-xfat"   />

    6) 修改登录按钮

<input type="hidden" name="lt" value="${loginTicket}" />
<input type="hidden" name="execution" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
<input class="sui-btn btn-block btn-xlarge btn-danger" accesskey="l" value="登陆" type="submit" />

    7) 错误提示,在form内表单添加

<form:errors path="*" id="msg" cssClass="errors" element="div" htmlEscape="false" />

     8) 修改错误提示

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/cas-servlet.xml

     9) 在messages_zh_CN.properties添加以下内容

vim /usr/local/tomcat/apache-tomcat-7.0.52/webapps/cas/WEB-INF/classes/messages_zh_CN.properties
authenticationFailure.AccountNotFoundException=\u7528\u6237\u4E0D\u5B58\u5728. authenticationFailure.FailedLoginException=\u5BC6\u7801\u9519\u8BEF.

 spring-security整合cas  

  (1) 添加依赖

        <!-- spring安全框架 -->
        <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>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
<!-- cas --> <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>

   (2) 授权认证类

import java.util.ArrayList;
import java.util.List;

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;

public class UserDetailServiceImpl implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("UserDetailsServiceImpl : " + username);    
        // 角色授权
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
        authorities.add(authority);        
        return new User(username, "", authorities);
    }
}

   (3) spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"
    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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <context:property-placeholder location="classpath:properties/*.properties" />

    <!-- 以下页面不被拦截 -->
    <http pattern="/register.html" security="none"></http>
    <http pattern="/user/add.do" security="none"></http><!-- 放行注册请求 -->
    <http pattern="/user/sendVCode.do" security="none"></http><!-- 放行注册请求 -->
    <http pattern="/css/**" security="none"></http>
    <http pattern="/img/**" security="none"></http>
    <http pattern="/js/**" security="none"></http>
    <http pattern="/plugins/**" security="none"></http>
  <!-- (1)
   此配置是跳过security校验,所以:SecurityContextHolder.getContext().getAuthentication() = null
   <http pattern="/cart/*.do" security="none"></http> -->
<!-- spring-security整合CAS单点登录系统 --> <!-- entry-point-ref 入口点引用 --> <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">      <!-- (2)
      注入匿名访问的角色 -->
      <intercept-url pattern="/cart/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY" />

     <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://127.0.0.1:8080/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:9107/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="userDetailService" /> </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://127.0.0.1:8080/cas" />
</beans:bean> </beans:property> <beans:property name="key" value="an_id_for_this_auth_provider_only" /> </beans:bean> <!-- 认证类 --> <beans:bean id="userDetailService" class="com.xxx.user.service.impl.UserDetailServiceImpl" /> <!-- 认证过滤器 结束 --> <!-- 单点登出 开始 --> <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://127.0.0.1:8080/cas/logout?service=http://localhost:9107" /> <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) web.xml

    <welcome-file-list>
        <welcome-file>home-index.html</welcome-file>
    </welcome-file-list>

    <!-- post乱码过滤器 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 前端控制器 -->
    <servlet>
        <servlet-name>xxx-user-web</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>xxx-user-web</servlet-name>
        <!-- 拦截所有请求jsp除外 -->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <!-- spring安全框架 -->
    <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>

   (5) 页面登出代码

<span class="safe"> <a href="/logout/cas">退出登录 </a></span>

  (6) 获取登录名

@RestController
public class UserController {
    @RequestMapping("/findLoginUser")
    public void  findLoginUser(){
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        System.out.println(name);        
    }    
}

猜你喜欢

转载自www.cnblogs.com/lin-nest/p/10322624.html
今日推荐