cas-server-3.5.2 SSO 单点登入 带验证码 登入后可携带自定义用户信息(一)

xiaoxiao2021-02-28  99

第一次接触CAS SSO 单点登入,个人也是通过网上查阅各种资料,才完成自己想要的这个版本的。本来想一次把验证码和携带用户信息功能一次性弄完的,不过后来发现,光是携带验证码这一个就写了三四个小时,所以还是决定分两章讲解,本章主要是带着大家(主要是没接触过cas的人)了解cas,然后实现自带验证码的功能。

本版本的SSO单点登入基于cas-server-3.5.2(下载地址:http://download.csdn.net/download/jieyuanyihao/9959821)、cas-client-3.2.1(下载地址:http://download.csdn.net/download/jieyuanyihao/9959828),并且在原有的基础上增加了验证码验证,下一章用讲解登入后可以根据自己的需要返回其他的用户信息。好了废话不多说了,先来张登入页面的图片,自己做的,不好看,大家将就将就,背景图片百度上随便找的,请别说我侵权哦。本次学习内容比较多,大家有点儿耐心。

本次代码sso下载地址: http://download.csdn.net/download/jieyuanyihao/9960424;客户端下载地址:http://download.csdn.net/download/jieyuanyihao/9963273

1、首先大家下载cas-server-3.5.2-release.zip,解压cas-server-3.5.2-release.zip,进入文件夹modules,把cas-server-webapp-3.5.2.war这个war包开发tomcat webapp下,并改名为sso.war,启动tomcat后出现sso文件夹。把modules文件里面cas-server-support-generic-3.5.2.jar、cas-server-support-jdbc-3.5.2.jar、cas-server-support-ldap-3.5.2.jar架包拷贝到tomcat webapp下sso项目的lib里面。本次项目我们采用mysql数据,所以需要mysql-connector-java-5.1.40-bin.jar,额外还需要framework-core-bin2.0.jar架包。

2、接下来进入webapps\sso\WEB-INF,找到deployerConfigContext.xml文件,用纯文本编辑器打卡,找到

<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />把他注释掉,并且添加如下内容

<!-- <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> --> <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="dataSource" ref="dataSource" ></property> <property name="sql" value="select password from sys_user where user_name=?" ></property> </bean> 这里面引用到了一个dataSource,所以我们也需要增加一个dataSource的配置。

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/erp" /> <property name="username" value="root" /> <property name="password" value="root" /> </bean> 不过这里要注意这个配置的位置,如下图

这里我们需要在mysql中新建一个数据库,名称为erp,用户名密码都是root,在erp数据库中新建一张表 sys_user,里面至少需要两个字段user_name和password,当然这个都可以根据你的sql和配置来修改,这里就不多说了。在表里我们需要存入一个数据,user_name 为admin,密码为123456。

3、本次我们使用http协议,而不使用https协议,所以接下来我们进入tomcat\webapps\sso\WEB-INF\spring-configuration文件夹,找到文件ticketGrantingTicketCookieGenerator.xml,并用文本编辑器打开,找到下面内容

<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="true" p:cookieMaxAge="-1" p:cookieName="CASTGC" p:cookiePath="/cas" />把p:cookieSecure改成false即可

4、全部保存后,启动tomcat,打卡浏览器,输入网址 http://localhost:8080/sso,则会出现下面界面

输入用户名 admin,密码 123456,登入,登入成功,则会出现下面界面,如果不是,则说明你那里配置有错,或者数据库数据不对。

到此,cas sso基础知识已经学完了,接下来开始,使用我们自己的页面,添加验证码验证和返回用户信息。

5、首先我们需要新建一个web工程,工程名就叫sso吧。项目建成后把项目的pom.xml文件删除掉。

6、右击项目,选择build path,修改source,把test文件夹都去掉,把resource中excluded里面的去掉,输出文件夹目录改掉。

7、把webapps\sso文件夹下除了WEB-INF文件以外的所有文件拷贝到sso项目src/main/webapp文件夹下

然后把webapps\sso\WEB-INF下面除了classes文件夹以外的所有文件拷贝到sso项目的src/main/webapp/WEB-INF文件夹下

接下来从我们解压cas-server-3.5.2-release.zip后的文件夹中把目录cas-server-3.5.2\cas-server-webapp\src\main\java 中的文件夹拷贝到sso项目的Java Resources下面的src/main/java目录下面

此时项目可能会报错,不过没有关系,我们先把需要的文件全部拷贝过来之后再处理这个问题好了。把webapps\sso\WEB-INF\classes目录下除了org文件以为的所有文件拷贝到sso项目的Java Resource 下面的src/main/resources文件夹下

好了,接下来我们来处理刚刚的代码报错的问题。

右击sso项目,选择build path,选择相应的自己电脑版本的jdk,如雕maven库,同时点击add library按钮,选择web app library,选择当前的项目sso,点击finish按钮完成项目下lib架包的添加。再点击add library,选择server runtime,添加tomcat服务器,点击ok按钮保存。此时,项目就不会报错了。

现在项目的基本架构已经搭建好了,此时如果你运行项目,应该跟之前基础学习时是一样的效果。接下来我们一气呵成,添加自己的登入页面,增加验证码验证,同时返回我们需要的用户信息。

8、首先添加自己的登入页面,由于涉及页面布局比较烦,这里不做过多的解释,具体源码大家可以在文章开头链接地址下载,这里只展示登入页面的jsp代码,修改/sso/src/main/webapp/WEB-INF/view/jsp/default/ui/casLoginView.jsp代码,改成下面的:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <%@ page session="true"%> <%@ 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"%> <spring:theme code="mobile.custom.css.file" var="mobileCss" text="" /> <c:set var="ctxPath" value="<%=request.getContextPath()%>" /> <html xmlns="http://www.w3.org/1999/xhtml" lang="zn_CN"> <head> <title>ERP资源管理系统-用户登录</title> <spring:theme code="standard.custom.css.file" var="customCssFile" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="icon" href="<c:url value="/favicon.ico" />" type="image/x-icon" /> <link rel="stylesheet" type="text/css" href="${ctxPath}/css/style.css" /> <script type="text/javascript"> function refreshCode(that) { that.src = "${ctxPath}/validCodeImage.html?rnd" + Math.random(); } </script> </head> <body id="cas" class="login"> <div class="wrap"> <div class="main"> <div id="content" class="login-box"> <div class="box fl-panel" id="login"> <form:form method="post" id="fm1" cssClass="fm-v clearfix" commandName="${commandName}" htmlEscape="true"> <a class="title"><spring:message code="screen.welcome.welcome" /></a> <table class="table1"> <tr> <td class="td1" /> </tr> </table> <table class="table1"> <tr> <td class="td1" /> </tr> </table> <form:errors path="*" id="msg" cssClass="errors" element="div" /> <table class="table1"> <tr> <td class="td1" /> </tr> </table> <table class="table1"> <tr> <td><img src="${ctxPath}/images/login/name.png" class="img1" align="middle" /></td> <td><input type="text" id="username" name="username" class="text1" /></td> </tr> <tr> <td class="td1" /> </tr> <tr> <td><img src="${ctxPath}/images/login/pw.png" class="img1" align="middle" /></td> <td><input type="password" id="password" name="password" class="text1" /></td> </tr> </table> <table class="table1"> <tr> <td class="td1" /> </tr> </table> <table class="table2"> <tr> <td><img src="${ctxPath}/images/login/check.png" class="img1" align="middle" /></td> <td><input type="text" id="validCode" name="validCode" class="text2" /></td> <td class="td2"></td> <td><img src="${ctxPath}/validCodeImage.html?rnd=<%=Math.random() %>" οnclick="refreshCode(this);" class="img2"/></td> </tr> </table> <table class="table1"> <tr> <td class="td1" /> </tr> </table> <div class="btn-row"> <input type="hidden" name="lt" value="${loginTicket}" /> <input type="hidden" name="execution" value="${flowExecutionKey}" /> <input type="hidden" name="_eventId" value="submit" /> <input class="btn1" name="submit" accesskey="l" value="<spring:message code="screen.welcome.button.login" />" tabindex="4" type="submit" /> <a>  </a> <input class="btn1" name="reset" accesskey="c" value="<spring:message code="screen.welcome.button.clear" />" tabindex="5" type="reset" /> </div> </form:form> </div> </div> </div> </div> <div class="bottom"> <a style="color: black;">网上备案号123456</a> </div> </body> </html> 重点是多了一个验证码的图片,和验证码的输入框,这里的url要注意,后面配置的时候要用到的。 9、接下是配置servlet,能后调用后台,获取验证码,以及登入时添加验证码的验证。修改web.xml文件,添加获取验证码的方法的servlet,主要url-pattern要和jsp里面一致。   <servlet-mapping> <servlet-name>cas</servlet-name> <url-pattern>/validCodeImage.html</url-pattern> </servlet-mapping>

10、修改cas-servlet.xml,添加获取验证码方法,首先找到bean id=“handlerMappingC”的,添加

<!-- 增加获取验证码的方法 --> <prop key="/validCodeImage.html">validCodeImageCreateController</prop> 注意,从现在开始,所有的命名都是有意义的,不要随便修改,否则会出现很多奇怪的问题的。然后在该配置文件最下面添加对应的bean。

<!-- 增加获取验证码的方法 --> <bean id="validCodeImageCreateController" class="org.jasig.cas.web.ValidCodeImageCreateController" />

11、添加bean所对应的ValidCodeImageCreateController类,如果报错,请确保自己项目的java compiler和project facets的java版本高于1.6.

package org.jasig.cas.web; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.OutputStream; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.InitializingBean; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class ValidCodeImageCreateController implements Controller,InitializingBean{ @Override public void afterPropertiesSet() throws Exception { } @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { BufferedImage buffer = new BufferedImage(60, 23, BufferedImage.TYPE_INT_RGB); Graphics g = buffer.getGraphics(); String code = randomValidCode(); request.getSession().setAttribute("__VALID_IMAGE_CODE__", code); //背景色 g.setColor(new Color(0xbf0d0d)); g.fillRect(0, 0, 60, 23); //干扰线 // g.setColor(Color.GRAY); // for(int i = 0; i < 3; i++) // g.drawLine((int) (Math.random()*60), (int) (Math.random()*23), (int) (Math.random()*60), (int) (Math.random()*23)); g.setFont(new Font(Font.SANS_SERIF, Font.BOLD | Font.ITALIC, 18)); g.setColor(Color.WHITE); for(int i = 0; i < 4; i++){ //随机色 随机位置 // int rgb = (int) (Math.random() * 0x999999); // g.setColor(new Color(rgb)); // g.drawString(String.valueOf(code.charAt(i)), (int) (Math.random()*5) + i*15, (int) (Math.random()*8) + 10); g.drawString(String.valueOf(code.charAt(i)), i*14+2, 17); } g.dispose(); response.setContentType("image/jpeg"); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); OutputStream os = response.getOutputStream(); ImageIO.write(buffer, "PNG", os); os.flush(); os.close(); return null; } private String randomValidCode(){ // String randChars = "1234567890abcdefghijklmnopqrstuvwsxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // String randChars = "123456789abcdefghjkmnopqrstuvwsxyzABCDEFGHJKMNPQRSTUVWXYZ"; String randChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; StringBuffer code = new StringBuffer(); int n, m; for(m = 0; m < 4; m++){ n = (int) (Math.random() * randChars.length()); code.append(randChars.charAt(n)); } return code.toString(); } }

此时登入页面应该已经可以出现验证码了。

12、接下就是添加验证码验证功能了。

首先修改login-webflow.xml文件中找到

<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" /> 这一行,注释掉,改成 <!-- <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" /> --> <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCaptchaCredentials" />

并且添加新的类UsernamePasswordCaptchaCredentials,因为我们登入信息多了一个验证码。

package org.jasig.cas.authentication.principal; import org.jasig.cas.authentication.principal.UsernamePasswordCredentials; public class UsernamePasswordCaptchaCredentials extends UsernamePasswordCredentials{ /** * */ private static final long serialVersionUID = 605301317353722284L; private String validCode; public String getValidCode() { return validCode; } public void setValidCode(String validCode) { this.validCode = validCode; } }

修改cas-servlet.xml文件中bean id="authenticationViaFormAction",改成下面配置

<!-- <bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction" --> <bean id="authenticationViaCaptchaFormAction" class="org.jasig.cas.web.flow.SsoAuthenticationViaFormAction" p:centralAuthenticationService-ref="centralAuthenticationService" p:warnCookieGenerator-ref="warnCookieGenerator"/>

同时新增类SsoAuthenticationViaFormAction

package org.jasig.cas.web.flow; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.jasig.cas.authentication.principal.Credentials; import org.jasig.cas.authentication.principal.UsernamePasswordCaptchaCredentials; import org.jasig.cas.web.support.WebUtils; import org.springframework.binding.message.MessageBuilder; import org.springframework.binding.message.MessageContext; import org.springframework.util.StringUtils; import org.springframework.webflow.execution.RequestContext; public class SsoAuthenticationViaFormAction extends AuthenticationViaFormAction{ public final String validatorCaptcha(final RequestContext context, final Credentials credentials, final MessageContext messageContext) { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); HttpSession session = request.getSession(); String validCode = (String) session.getAttribute("__VALID_IMAGE_CODE__"); session.removeAttribute("__VALID_IMAGE_CODE__"); UsernamePasswordCaptchaCredentials upc = (UsernamePasswordCaptchaCredentials) credentials; String submitAuthcodeCaptcha = upc.getValidCode(); if (!StringUtils.hasText(submitAuthcodeCaptcha) || !StringUtils.hasText(submitAuthcodeCaptcha)) { // messageContext.addMessage(new MessageBuilder().code("required.validCode").build()); messageContext.addMessage(new MessageBuilder().error().code("required.validCode").defaultText("required.validCode").build()); return "error"; } if (submitAuthcodeCaptcha.toUpperCase().equals(validCode)) { return "success"; } // messageContext.addMessage(new MessageBuilder().code("error.authentication.validCode.bad").build()); messageContext.addMessage(new MessageBuilder().error().code("error.authentication.validCode.bad").defaultText("error.authentication.validCode.bad").build()); return "error"; } }这里需要在src/main/resource/下面的message配置文件中添加错误信息提示,我们常用的是英文和中文,所以就在英文和中文的配置文件里加加好了,后期熟悉了,自己可以随意加。同事把screen.welcome.welcome的配置信息也改了,改成

screen.welcome.welcome=\u6B22\u8FCE\u4F7F\u7528ERP\u8D44\u6E90\u7BA1\u7406\u7CFB\u7EDF required.validCode=\u5FC5\u987B\u8F93\u5165\u9A8C\u8BC1\u7801 error.authentication.validCode.bad=\u60A8\u8F93\u5165\u7684\u9A8C\u8BC1\u7801\u6709\u8BEF

13、接下来我们就要修改登入流程了,修改login-webflow.xml文件,找到

<view-state id="viewLoginForm" view="casLoginView" model="credentials"> 在 <binder>里面增加验证码字段,同时把流程第一步改成验证验证码.

具体代码如下

<view-state id="viewLoginForm" view="casLoginView" model="credentials">         <binder>             <binding property="username" />             <binding property="password" />             <!-- 添加校验码字段 -->             <binding property="validCode" />         </binder>         <on-entry>             <set name="viewScope.commandName" value="'credentials'" />         </on-entry> <transition on="submit" bind="true" validate="true" to="validatorCode">             <evaluate expression="authenticationViaCaptchaFormAction.doBind(flowRequestContext, flowScope.credentials)" />         </transition> </view-state> <!-- 添加一个 validatorCaptcha 校验验证码的操作 -->   <action-state id="validatorCode">      <evaluate expression="authenticationViaCaptchaFormAction.validatorCaptcha(flowRequestContext, flowScope.credentials, messageContext)"></evaluate>      <transition on="error" to="generateLoginTicket" />      <transition on="success" to="realSubmit" />   </action-state>    <action-state id="realSubmit">         <evaluate expression="authenticationViaCaptchaFormAction.submit(flowRequestContext, flowScope.credentials, messageContext)" />         <!--      To enable LPPE on the 'warn' replace the below transition with:      <transition on="warn" to="passwordPolicyCheck" />      CAS will attempt to transition to the 'warn' when there's a 'renew' parameter      and there exists a ticketGrantingId and a service for the incoming request.    --> <transition on="warn" to="warn" /> <!--      To enable LPPE on the 'success' replace the below transition with:      <transition on="success" to="passwordPolicyCheck" />    --> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="generateLoginTicket" /> <transition on="accountDisabled" to="casAccountDisabledView" />    <transition on="mustChangePassword" to="casMustChangePassView" />    <transition on="accountLocked" to="casAccountLockedView" />    <transition on="badHours" to="casBadHoursView" />    <transition on="badWorkstation" to="casBadWorkstationView" />    <transition on="passwordExpired" to="casExpiredPassView" /> </action-state> 到此添加验证码功能已经结束了。源码链接在文章开头处有。

下一章将会把返回并携带用户信息的功能添加进去。

声明,本文部分内容转载自:http://blog.csdn.net/lifetragedy/article/details/43817903 ,这个人写的博客还是不错,大家可以进去看看。

转载请注明原文地址: https://www.6miu.com/read-67122.html

最新回复(0)