您的位置:首页 > 其它

CAS之5.2x版本登录验证码-yellowcong

2018-02-08 00:33 435 查看
系统验证码 或者邮箱验证等,这个都是必须的,不然你搞个机器人注入 啥的,我咋玩。首先声明,这个5.2.x的和5.1.x的有所区别,有的时候,不通用,需要注意点,我这个地方,以5.2.x讲解,如果需要5.1.x的请自己研究,或则联系我。实现自定义ajax验证码的步骤:1、创建控制器。2、配置到springboot、3、配置spring.factories文件。4、配置自定义的界面、5、添加js的配置。

代码地址

https://gitee.com/yellowcong/springboot_cas/tree/master/cas-server-code


工程目录



注册控制器到cas

1、创建控制器

我们需要创建 一个代码控制器,这个同普通的springmvc是没有啥区别的。

package com.yellowcong.auth.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yellowcong.auth.code.CaptchaCodeUtils;
import com.yellowcong.auth.code.CaptchaCodeUtils.CaptchaCode;
import com.yellowcong.auth.constants.Constants;

@Controller
public class CaptchaController {

/**
* 创建日期:2018/02/07<br/>
* 创建时间:8:36:28<br/>
* 创建用户:yellowcong<br/>
* 机能概要: 写数据到客户端
* @param request
* @param response
* @throws Exception
*/
@GetMapping(value = Constants.REQUEST_MAPPING, produces = "image/png")
public void handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
OutputStream out = null;
try {
//设置response头信息
//禁止缓存
response.setHeader("Cache-Control", "no-cache");
response.setContentType("image/png");
//存储验证码到session
CaptchaCode code = CaptchaCodeUtils.getInstance().getCode();

//获取验证码code
String codeTxt = code.getText();
request.getSession().setAttribute(Constants.STORE_CODE, codeTxt);
//写文件到客户端
out = response.getOutputStream();
byte[] imgs = code.getData();
out.write(imgs, 0, imgs.length);
out.flush();
} finally {
if(out != null) {
out.close();
}
}
}

/**
* 创建日期:2018年2月7日<br/>
* 创建时间:下午10:09:29<br/>
* 创建用户:yellowcong<br/>
* 机能概要:验证码比对
* @param code
* @param req
* @param resp
*/
@RequestMapping(value="/chkCode",method=RequestMethod.POST)
public void checkJSON(String code,HttpServletRequest req,HttpServletResponse resp) {

//获取session中的验证码
String storeCode = (String)req.getSession().getAttribute(Constants.STORE_CODE);
code = code.trim();
//返回值
Map<String,Object> map = new HashMap<String, Object>();
//验证是否对,不管大小写
if(!StringUtils.isEmpty(storeCode) && code.equalsIgnoreCase(storeCode)) {
map.put("error", false);
map.put("msg", "验证成功");
}else if (StringUtils.isEmpty(code)){
map.put("error", true);
map.put("msg", "验证码不能为空");
}else {
map.put("error", true);
map.put("msg", "验证码错误");
}
this.writeJSON(resp, map);
}

/**
* 在SpringMvc中获取到Session
* @return
*/
public void writeJSON(HttpServletResponse response,Object object){
try {
//设定编码
response.setCharacterEncoding("UTF-8");
//表示是json类型的数据
response.setContentType("application/json");
//获取PrintWriter 往浏览器端写数据
PrintWriter writer = response.getWriter();

ObjectMapper mapper = new ObjectMapper(); //转换器
//获取到转化后的JSON 数据
String json = mapper.writeValueAsString(object);
//写数据到浏览器
writer.write(json);
//刷新,表示全部写完,把缓存数据都刷出去
writer.flush();

//关闭writer
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


2、配置到springboot

我们创建action后,需要通过CaptchaConfiguration 来注册到cas上。

package com.yellowcong.auth.conf;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.yellowcong.auth.controller.CaptchaController;

/**
* 创建日期:2018/02/07<br/>
* 创建时间:8:38:31<br/>
* 创建用户:yellowcong<br/>
* 机能概要:自定义控制器
*/
@Configuration("captchaConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CaptchaConfiguration {

// 注册bean到spring容器
@Bean
@ConditionalOnMissingBean(name = "captchaController")
public CaptchaController captchaController() {
return new CaptchaController();
}
}


3、配置spring.factories 文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yellowcong.auth.conf.CaptchaConfiguration


4、界面

界面添加了一个验证码表的图片,但是没有通过表单提交的方式提交到后台。界面的搭建,需要大家明白如何引入js资源文件,通过th:src的这种方式

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title th:text="${#themes.code('yellowcong.pageTitle')}"></title>
<link rel="stylesheet" th:href="@{${#themes.code('yellowcong.css.file')}}"/>
<script type="text/javascript" th:src="@{/themes/yellowcong/js/jquery-1.7.1.js}" ></script>
<script type="text/javascript" th:src="@{/themes/yellowcong/js/code.js}" ></script>

</head>

<body>
<h1 th:text="${#themes.code('yellowcong.pageTitle')}"></h1>
<h2>yellowcong的登录模板</h2>
<div>
<form method="post" th:object="${credential}">
<div th:if="${#fields.hasErrors('*')}">
<span th:each="err : ${#fields.errors('*')}" th:utext="${err}"/>
</div>
<h2 th:utext="#{screen.welcome.instructions}"></h2>

<section class="row">
<label for="username" th:utext="#{screen.welcome.label.netid}"/>
<div th:unless="${openIdLocalId}">
<input class="required"
id="username"
size="25"
tabindex="1"
type="text"
th:disabled="${guaEnabled}"
th:field="*{username}"
th:accesskey="#{screen.welcome.label.netid.accesskey}"
autocomplete="off"/>
</div>
</section>

<section class="row">
<label for="password" th:utext="#{screen.welcome.label.password}"/>
<div>
<input class="required"
type="password"
id="password"
size="25"
tabindex="2"
th:accesskey="#{screen.welcome.label.password.accesskey}"
th:field="*{password}"
autocomplete="off"/>
</div>
</section>
<!-- 验证码信息 -->
<section>
<img id="captcha_img" th:src="@{/captcha}" onclick="changeCode()" style="width: 125px;"/>
<input type="text" id="code"/>
<span id="code_str"></span>
</section>
<section>
<input type="hidden" name="execution" th:value="${flowExecutionKey}"/>
<input type="hidden" name="_eventId" value="submit"/>
<input type="hidden" name="geolocation"/>
<input class="btn btn-submit btn-block"
name="submit"
accesskey="l"
th:value="#{screen.welcome.button.login}"
tabindex="6"
type="submit"/>
</section>
</form>
</div>
</body>
</html>


5、js验证

这个js验证,只是简单的做了切换验证码和验证码的ajax验证。

$(function(){
//验证码验证
$("#code").blur(function(){
var codeStr = $("#code").val();

if(codeIsError()){
console.log("验证失败");
}else{
console.log("验证成功");
}
});
});
//---------------------------------------------------------------------
//检查验证码是否正确
//---------------------------------------------------------------------
function changeCode(){
//修改验证码
$("#captcha_img").attr('src','/captcha?id='+uuid());
}
//-------------------------------------------------------------------------------------------
//生成UUID
//-------------------------------------------------------------------------------------------
function uuid(){
//获取系统当前的时间
var d = new Date().getTime();
//替换uuid里面的x和y
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
//取余 16进制
var r = (d + Math.random()*16)%16 | 0;
//向下去整
d = Math.floor(d/16);
//toString 表示编程16进制的数据
return (c=='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid;
};
//---------------------------------------------------------------------
//检查验证码是否正确
//---------------------------------------------------------------------
function codeIsError(){
var error = true;
var codeStr = $("#code").val();
if(codeStr == ""){
setCodeInfo(error,"验证码不能为空");
return error;
}
//请求地址,你们最好注意一下,这个地方可能报错需要修改,
$.ajax({
type : "post",  //使用提交的方法 post、get
url : contextPath()+"/chkCode",   //提交的地址
data : { code:$("#code").val() },  //数据
async : false,   //配置是否
dataType:"json",//返回数据类型的格式
success : function(data){  //回调操作
console.log(data);
error = data.error;

setCodeInfo(error,data.msg);
}
});
return error;
}
//设定验证码的错误提示消息
function setCodeInfo(error,msg){
if(error){
$("#code_str").html("<font color='red'>"+msg+"</font>");
}else{
$("#code_str").html("<font color='blue'>"+msg+"</font>");
}
}
// 获取到当前项目的名称
var contextPath = function() {
var path = "/" + location.pathname.split("/")[1];
//当项目的目录是根目录的情况
if(path == "/login"){
return "";
}else{
return path;
}
}


配置pom.xml

为啥我会把pom.xml单独拿出来说一下,因为一般我们在pom中,还需要添加
cas-server-core-configuration
的依赖,不然就会报错,说找不到配置类,这个问题以前也讲过

<!-- 单独导入cas的配置依赖到项目中 -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration</artifactId>
<version>${cas.version}</version>
<scope>system</scope>
<optional>true</optional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jar</systemPath>
</dependency>


完整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 ">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-code</artifactId>
<packaging>war</packaging>
<version>1.0</version>

<dependencies>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp${app.server}</artifactId>
<version>${cas.version}</version>
<type>war</type>
<scope>system</scope>
<optional>true</optional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-webapp-tomcat-${cas.version}.war</systemPath>
</dependency>

<!-- 自定义认证的方式 begin -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-webflow</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-authentication</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp-config</artifactId>
<version>${cas.version}</version>
<scope>provided</scope>
</dependency>

<!-- 单独导入cas的配置依赖到项目中 -->

<!-- 单独导入cas的配置依赖到项目中 --> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-core-configuration</artifactId> <version>${cas.version}</version> <scope>system</scope> <optional>true</optional> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jar</systemPath> </dependency>

<!-- <dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-redis-ticket-registry</artifactId>
<version>${cas.version}</version>
</dependency> -->

<!-- 数据库驱动 -->
<!-- MYSQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

<!-- servlet 的依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-osgi</artifactId>
<version>1.4.10.Final</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.rimerosolutions.maven.plugins</groupId>
<artifactId>wrapper-maven-plugin</artifactId>
<version>0.0.4</version>
<configuration>
<verifyDownload>true</verifyDownload>
<checksumAlgorithm>MD5</checksumAlgorithm>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
<configuration>
<mainClass>${mainClassName}</mainClass>
<addResources>true</addResources>
<executable>${isExecutable}</executable>
<layout>WAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 添加依赖的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
<includeScope>system</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<warName>cas</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
<recompressZippedFiles>false</recompressZippedFiles>
<archive>
<compress>false</compress>
<manifestFile>${manifestFileToUse}</manifestFile>
</archive>
<overlays>
<overlay>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp${app.server}</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
</plugin>
</plugins>
<finalName>cas</finalName>
</build>

<properties>
<cas.version>5.2.1</cas.version>
<springboot.version>1.5.8.RELEASE</springboot.version>
<!-- app.server could be -jetty, -undertow, -tomcat, or blank if you plan to provide appserver -->
<app.server>-tomcat</app.server>

<mainClassName>org.springframework.boot.loader.WarLauncher</mainClassName>
<isExecutable>false</isExecutable>
<manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MF</manifestFileToUse>

<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
<repository>
<id>sonatype-releases</id>
<url>http://oss.sonatype.org/content/repositories/releases/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>shibboleth-releases</id>
<url>https://build.shibboleth.net/nexus/content/repositories/releases</url>
</repository>
</repositories>

<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<id>exec</id>
<properties>
<mainClassName>org.apereo.cas.web.CasWebApplication</mainClassName>
<isExecutable>true</isExecutable>
<manifestFileToUse></manifestFileToUse>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>echo-maven-plugin</artifactId>
<version>0.3.0</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>echo</goal>
</goals>
</execution>
</executions>
<configuration>
<echos>
<echo>Executable profile to make the generated CAS web application executable.</echo></echos>
</configuration>
</plugin>
</plugins>
</build>
</profile>

<profile>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<id>pgp</id>
<build>
<plugins>
<plugin>
<groupId>com.github.s4u.plugins</groupId>
<artifactId>pgpverify-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<pgpKeyServer>hkp://pool.sks-keyservers.net</pgpKeyServer>
<pgpKeysCachePath>${settings.localRepository}/pgpkeys-cache</pgpKeysCachePath>
<scope>test</scope>
<verifyPomFiles>true</verifyPomFiles>
<failNoSignature>false</failNoSignature>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>


测试

这个地方做的是验证码的功能,具体更加严密的逻辑可以你们自己添加,我就实现了部分校验功能



常见问题

找不到类CasConfigurationProperties



解决办法,单独导入配置
cas-server-core-configuration
的依赖包。

<!-- 单独导入cas的配置依赖到项目中 -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration</artifactId>
<version>${cas.version}</version>
<scope>system</scope>
<optional>true</optional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jar</systemPath>
</dependency>


端口占用

刚刚弄完springboot,可能调试端口没有关闭,所以包的这个错

ERROR: transport error 202: bind failed: Address already in use
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debu
gInit.c:750]




解决办法

#关闭java web的进程
taskkill /f /t /im javaw.exe

#关闭java的进程
taskkill /f /t /im java.exe




参考文章

http://blog.csdn.net/yelllowcong/article/details/79281705
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: