cas server 基础 数据库 验证码实现及其配置

由于需要从业务上将系统拆分成多个独立的子系统,所以需要sso。这里主要是讲述一下server 端的配置.

下面按照几个步骤进行描述
  1. 下载cas-server-4.1.9 (https://github.com/apereo/cas)
  2. 构建 server (maven)工程。
  3. 目录结构
  4. 基本配置
  5. 验证码配置
1、下载
在 https://github.com/apereo/cas 可以下载cas-server 的源代码
也可以在直接使用maven 进行构建。
如果是下载源码,那么复制里面的工程(cas-server-webapp)也是一样的
2、构建工程(如果是直接下载源码 跳过这个步骤)
1、创建一个maven 工程, 后面附上 依赖文件。
2、复制从github 下载的 cas-server-webapp 中 src/main/webapp  内容 到 webapp 中,并且将resources 中的文件复制到 resources 中,目的是减少配置。
这两个文件夹中主要是配置文件。不要遗漏。
    pom.xml 文件。 

    <properties>
        <spring.version>3.2.6.RELEASE</spring.version>
        <cas-server.version>4.1.9</cas-server.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.jasig.cas</groupId>
            <artifactId>cas-server-webapp-support</artifactId>
            <version>${cas-server.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.jasig.cas</groupId>
            <artifactId>cas-server-security-filter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.jasig.cas</groupId>
            <artifactId>cas-server-support-jdbc</artifactId>
            <version>${cas-server.version}</version>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.22</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.1.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.ryantenney.metrics</groupId>
            <artifactId>metrics-spring</artifactId>
            <version>3.0.1</version>
        </dependency>
    </dependencies>
3、目录结构
  • resource/services 的json 文件是配置那些服务允许访问cas 的。如果这里没有配置,那么可能会在其他工程跳转到cas 登录的时候出现不被允许的错误。
  • resouces/messages.properties 国际化配置。
  • WEB-INF/spring-configuration 一些基础的配置。一般不需要去修改
  • WEB-INF/view 文件页面存放目录
  • WEB-INF/webflow 工作流的配置文件
  • WEB-INF/cas.properties 基础属性的配置文件在有些xml 可以在看${xxxx:yyy} xxxx 就是里面的配置文件
  • WEB-INF/web.xml
  • WEB-INF/deployerConfigContext.xml 这个是部署的配置文件,主要修改的也就是这个文件
  • WEB-INF/cas-servlet.xml cas 主要是使用的spring mvc security webflow , 这个就是springmvc 配置文件
4、基础配置
  1. 很多教程都是一来就介绍怎么配置https 这里先不进行ssl 配置,使用http

    • cookie 配置 默认使用https 的方式,如果使用http 将不会创建全局的cookie
    WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml

   <!--  TODO 这里将 cookieSecure 修改为了false ,目的是使用http  -->
    <bean id="ticketGrantingTicketCookieGenerator"
    class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
          c:casCookieValueManager-ref="cookieValueManager"
          p:cookieSecure="false"
          p:cookieMaxAge="-1"
          p:cookieName="TGC"
          p:cookiePath=""/>
- 国际化的配置  WEB-INF/cas-servlet.xml
    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver"
        p:defaultLocale="zh_CN" />
- 认证处理配置 WEB-INF/deployerConfigContext.xml
        <!--  TODO 这里设置 p:requireSecure="false" 目的是为了使用http   -->
        <bean id="proxyAuthenticationHandler"
              class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
              p:requireSecure="false"
              p:httpClient-ref="supportsTrustStoreSslSocketFactoryHttpClient" />
这样http 就配置完成了! 可以进行测试一下了
  1. 数据库认证配置
 <!--  加密方式配置   -->
    <bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
        <constructor-arg index="0" value="MD5" />
    </bean>

    <!-- Oracle connector -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"    />
        <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:ytym"   />
        <property name="username" value="xxx"  />
        <property name="password" value="xxx"  />
    </bean>

    <!-- 使用自定义的查询方式验证用户信息 -->
    <bean id="primaryAuthenticationHandler"
          class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
        <property name="dataSource" ref="dataSource" />
        <property name="passwordEncoder" ref="MD5PasswordEncoder"/>
        <property name="sql" value="select login_pass from user where name = ?  " />
    </bean>

==QueryDatabaseAuthenticationHandler可以自己实现,根据业务的需要==

3、允许使用cas 认证的服务配置。

默认的配置是用是json 的格式进行配置 resource/services 文件中,但是修改起来难度比较大, 所以这里使用xml 的配置

找到 WEB-INF/deployerConfigContext.xml 中的 serviceRegistryDao 进行修改

<!-- 这里注释掉, 使用xml 的配置 方式 -->
    <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"
          p:registeredServices-ref="registeredServicesList" />

    <util:list id="registeredServicesList">
        <!--<bean class="org.jasig.cas.services.RegexRegisteredService">-->
            <!--<property name="id" value="10000001"/>-->
            <!--<property name="name" value="HTTPS and IMAPS"/>-->
            <!--<property name="description" value="This service definition authorized all application urls that support HTTPS and IMAPS protocols."/>-->
            <!--<property name="serviceId" value="^(https|imaps)://.*"/>-->
            <!--<property name="evaluationOrder" value="10000001"/>-->
        <!--</bean>-->
        <bean class="org.jasig.cas.services.RegexRegisteredService">
            <property name="id" value="10000002"/>
            <property name="name" value="localhost Test"/>
            <property name="description" value="local server config"/>
            <property name="serviceId" value="^(http?|https?|imaps?)://((127\.0\.0\.1)|(localhost)|(test.com))(:[\d]+)?/.*"/>
            <property name="evaluationOrder" value="10000002"/>
        </bean>
        <bean class="org.jasig.cas.services.RegexRegisteredService">
            <property name="id" value="10000003"/>
            <property name="name" value="ydzx online website"/>
            <property name="description" value="ydzx online"/>
            <property name="serviceId" value="^(http?|https?|imaps?)://[\w]+.ydzxlm.com/.*"/>
            <property name="evaluationOrder" value="10000002"/>
        </bean>
    </util:list>
5.验证码配置
自己写验证码的实现,并且写好验证码验证的接口

实现可以见后面的代码

1、在 配置验证bean
    WEB-INF/cas-servlet.xml
      <!-- 验证码验证 验证码超时时间,默认是五分钟 -->
  <bean id="authCodeValidateFormAction" class="com.ydzx.cas.server.web.flow.AuthCodeValidateFormAction" />
2、配置登录流程
    WEB-INF/webflow/login/login-webflow.xml
        <view-state id="viewLoginForm" view="casLoginView" model="credential">
        <binder>
            <binding property="username" required="true"/>
            <binding property="password" required="true"/>
        </binder>
        <on-entry>
            <set name="viewScope.commandName" value="‘credential‘"/>

            <!--
            <evaluate expression="samlMetadataUIParserAction" />
            -->
        </on-entry>
        <!--<transition on="submit" bind="true" validate="true" to="realSubmit"/>-->
        <!-- 修改,目的是在登录的时候,加上验证码的验证 -->
        <transition on="submit" bind="true" validate="true" to="authCodeValidate"/>
    </view-state>

        <!-- 添加一个新的流程,在登录前添加验证码 -->
    <action-state id="authCodeValidate" >
        <evaluate expression="authCodeValidateFormAction.validate(flowRequestContext,flowScope.credential, messageContext)" />
        <transition on="success" to="realSubmit" />
        <transition on="error" to="generateLoginTicket" />
    </action-state>

验证码 相关代码


验证码实现类 : VerfiyCode.java
public class VerfiyCode {
    private String randomCode;

    public VerfiyCode() {
        System.setProperty("java.awt.headless", "true");
    }

    Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    /**
     * 获取图片
     */
    public BufferedImage getImage() {
        // 在内存中创建图象
        int width = 60, height = 20;
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);

        // 获取图形上下
        Graphics g = image.getGraphics();

        // 生成随机
        Random random = new Random();

        // 设定背景
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);

        // 设定字体
        g.setFont(new Font("Times New Roman", Font.PLAIN, 18));

        // 画边
        g.setColor(new Color(255, 255, 255));
        g.drawRect(0, 0, width - 1, height - 1);

        // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测
        g.setColor(getRandColor(160, 200));
        for (int i = 0; i < 155; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 取随机产生的认证 (4位数 )
        String sRand = "";
        for (int i = 0; i < 4; i++) {
            String rand = String.valueOf(random.nextInt(10));
            sRand += rand;
            // 将认证码显示到图象中
            g.setColor(new Color(20 + random.nextInt(110), 20 + random
                    .nextInt(110), 20 + random.nextInt(110)));
            // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生
            g.drawString(rand, 13 * i + 6, 16);
        }

        // 将认证码存入
        this.setRandomCode(sRand);
        // session.setAttribute("rand",sRand);

        // 图象生效
        g.dispose();

        // 输出图象到页
        return image;
    }

    /**
     * 随机数
     */
    public String getRandomCode() {
        return this.randomCode;
    }

    public void setRandomCode(String randomCode) {
        this.randomCode = randomCode;
    }
}
AuthCodeValidateFormAction.java 验证码验证实现
public class AuthCodeValidateFormAction {
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    private long outTime = 5*60*1000;

    public static final String SUCCESS = "success";
    public static final String ERROR = "error";

    public Event validate(final RequestContext context, final Credential credential,
                             final MessageContext messageContext) {
        try {
            HttpServletRequest request = WebUtils.getHttpServletRequest(context);
            String image_code = (String) request.getSession().getAttribute("image_no");
            Long image_create_time = (Long) request.getSession().getAttribute("image_create_time");

            if( (image_create_time != null && Math.abs(System.currentTimeMillis() - image_create_time) > outTime)
                    || (image_code == null)   ){
                resultMsgWrapper(messageContext,"验证码超时!");
                return new Event(this, ERROR);
            }

            String username = request.getParameter("username");
            if (username == null) {
                resultMsgWrapper(messageContext,"用户信息不能为空!");
                return new Event(this, ERROR);
            }

            String[] separator_chars = username.split("#@#");

            if(separator_chars.length < 2){
                resultMsgWrapper(messageContext,"信息不合法!");
                return new Event(this, ERROR);
            }

            if(separator_chars[1] == null && StringUtils.isEmpty(separator_chars[1])){
                resultMsgWrapper(messageContext,"验证码不能为空!");
                return new Event(this, ERROR);
            }

            if (image_code != null && image_code.trim().equals(separator_chars[1])) {
                request.getSession().removeAttribute("image_no");
            } else {
                resultMsgWrapper(messageContext,"验证码信息错误!");
                return new Event(this, ERROR);
            }
            return newEvent(SUCCESS);
        } catch (final Exception e) {
            logger.debug(e.getMessage(), e);
            return newEvent(ERROR, e);
        }
    }

    private void resultMsgWrapper(MessageContext messageContext,String msg) {
        MessageBuilder msgBuilder = new MessageBuilder();
        msgBuilder.defaultText(msg);
        messageContext.addMessage(msgBuilder.error().build());
    }

    /**
     * New event based on the given id.
     *
     * @param id the id
     * @return the event
     */
    private Event newEvent(final String id) {
        return new Event(this, id);
    }

    /**
     * New event based on the id, which contains an error attribute referring to the exception occurred.
     *
     * @param id    the id
     * @param error the error
     * @return the event
     */
    private Event newEvent(final String id, final Exception error) {
        return new Event(this, id, new LocalAttributeMap("error", error));
    }

    public long getOutTime() {
        return outTime;
    }

    public void setOutTime(long outTime) {
        this.outTime = outTime;
    }
}
    verifyCode.jsp 实现。
    <%@ page language="java" contentType="image/jpeg" pageEncoding="UTF-8"
         import="VerfiyCode,javax.imageio.ImageIO, javax.servlet.ServletContext,org.springframework.web.context.support.WebApplicationContextUtils,org.springframework.context.ApplicationContext"%>
<%
    try {
        //设置页面不缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.reset();
        VerfiyCode verfiyCode = new VerfiyCode();
        ImageIO.write(verfiyCode.getImage(), "JPEG", response.getOutputStream());
        //存放会话中
        session.setAttribute("image_no", verfiyCode.getRandomCode());
        session.setAttribute("image_create_time", System.currentTimeMillis());

        ServletContext servletContext = config.getServletContext();
//      ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
//      Cache verifyCodeCache = (Cache)applicationContext.getBean("verifyCodeCache");
//      Element element = new Element(verfiyCode.getRandomCode(), "");
//      verifyCodeCache.put(element);

        out.clear();
        out = pageContext.pushBody();
    } catch (Exception e) {
        System.out.println(e);
    }
%>
login.html 登录页面(WEB-INF/view/jsp/default/ui/casLoginView.jsp)(不能直接使用 只表达基础的意思)

    <form action ="login" id="fm1" >
        <input type="hidden" name="lt" value="${loginTicket}" />
        <input type="hidden" name="execution" value="${flowExecutionKey}" />
        <input type="hidden" name="_eventId" value="submit" />
        <input class="input1" type="hidden" id="username" path="username" autocomplete="off" htmlEscape="true" />

        <table>
            <tr>
                <td>用户名</td>
                <td><input name="name"></td>
            </tr>

            <tr>
                <td>密码</td>
                <td><password class="input1" id="password" tabindex="2" path="password" htmlEscape="true" autocomplete="off" /></td>
            </tr>

            <tr>
                <td>验证码</td>
                <td>
                <input name="name">
                <img id="imgValidateCode"   src="<%=request.getContextPath()%>/verifyCode.jsp?rd=1"  />
                </td>
            </tr>
            <Tr>
                <Td>  <button onclick="checkUser" >登录</button>
            </tr>
        </table>
    </form>
    <script>
    function checkUser(){
                $("#username").val($  $("#name").val() + "#@#" + $("#image_no").val() );
                $("#fm1").submit();
            }

    </script>
时间: 2024-11-04 18:44:06

cas server 基础 数据库 验证码实现及其配置的相关文章

CAS server 连接mysql的deployerConfigContext.xml配置

1.deployerConfigContext.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:p="http://www

Mvc4单点登录之二 Cas server端配置

上一篇博客Mvc4单点登录之一Cas简单介绍简单的介绍了cas的工作原理!这篇文章介绍一下Cas Server端的配置. 首先要说明Cas server 是一个java程序,所以首先要确定你的电脑上安装了JDK, 并且安装了Tomcat 服务器,如果不会装的话,那么可以从网上查一下资料,一把一把的!例如,我将tomcat安装在了E:\apache-tomcat-7.0.52. cas的下载地址 cas 客户端:  http://download.csdn.net/detail/zhanghong

Eclipse配置CAS server

1.下载cas server的源码包(我使用的是cas-server-3.5.2.1-release.zip) 2.解压压缩包到某个目录下,找到cas-server-3.5.2.1-release.zip\cas-server-3.5.2.1\modules下的cas-server-webapp-3.5.2.1.war文件 3.在eclipse中导入war file ---->  cas-server-webapp-3.5.2.1.war 4.右键项目Run As -> Run on serv

SQL Server 2016的数据库范围内的配置

SQL Server 2016真的让人眼前一亮.几天前微软就提供了RCO(候选发布版)版本的下载.我已经围观了一圈RCO版本,其中一个最拽的功能是数据库范围内的配置(Database Scoped Configuration),在今天的文章里我想谈谈它.补充几句:装好之后,居然发现没有SSMS,崩溃中,原来是在向导中就有独立的安装程序,好吧! 这配色,真是低调有内涵. 另外,如过你的电脑已经安装了就[Microsoft Visual Studio 2010 Shell(独立)Redistribu

SQL Server 2012 数据库镜像配置完整篇

"数据库镜像"是一种提高 SQL Server 数据库的可用性的解决方案. 镜像基于每个数据库实现,并且只适用于使用完整恢复模式的数据库.数据库镜像维护一个数据库的两个副本,这两个副本必须驻留在不同的 SQL Server 数据库引擎 服务器实例上. 通常,这些服务器实例驻留在不同位置的计算机上. 启动数据库上的数据库镜像操作时,在这些服务器实例之间形成一种关系,称为"数据库镜像会话".其中一个服务器实例使数据库服务于客户端("主体服务器"), 

【SSO单点系列】(4):CAS SERVER登录后用户信息的返回

接着上一篇,在上一篇中我们描述了怎么在CAS SERVER登录页上添加验证码,并进行登录.一旦CAS SERVER验证成功后,我们就会跳转到客户端中去.跳转到客户端去后,大家想一想,客户端总要获取用户信息吧,不然客户端是怎么知道登录的是哪个用户.那么客户端要怎么获取用户信息呢? 其实验证成功,跳转客户端这个过程中,CAS SERVER 会返回登录的相关信息给客户端,客户端只要进行获取,就能知道登录的具体是哪个用户了.不过CAS 默认只返回用户账号给客户端,那么怎么定义CAS SERVER返回的信

SQL Server基础

一.常用命令 1.使用命令行开启SQL Server服务 获取管理员权限的命令行工具: net start mssqlserver 开启sql server服务 net restart mssqlserver 重新启动sql server服务 net stop mssqlserver 关闭sql server服务 2.使用命令登陆(该方法可适用于在一台没有SQL Server的电脑去操作一台有SQL Server的电脑) 运行: sqpl ?/ [-S 服务器的名称]  [-U 登陆名] [-P

C# 操作 SQLCE,SQL Server Mobile数据库 .

整理几段操作 SQL Server Mobile 数据库的常用 C# 代码,供刚刚接触 SQL Server Mobile 开发的朋友参考. 1. 创建数据库// 创建数据库File.Delete("Test.sdf");SqlCeEngine engine = new SqlCeEngine(    "Data Source='Test.sdf';LCID=1033;Password=\"s$;2'!dS64\";Encrypt=TRUE;")

sql server 2012数据库镜像

sql server 2012数据库镜像 以下通过域帐户来配置数据库镜像: 一.环境准备 1.准备计算机 AD02为域控制器/DNS服务器(sz1card1.com),IP:192.168.2.218/24,AD02安装成为域控制器.DNS服务(这里不做演示) W67为主体服务器,IP:192.168.2.67/24,安装SQL SERVER 2012 企业核心版(这里不做演示) W65为镜像服务器,IP:192.168.2.65/24,安装SQL SERVER 2012 企业核心版(这里不做演