系统验证码 或者邮箱验证等,这个都是必须的,不然你搞个机器人注入 啥的,我咋玩。首先声明,这个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
我们需要创建 一个代码控制器,这个同普通的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
* 创建时间:8:36:28
* 创建用户:yellowcong
* 机能概要: 写数据到客户端
* @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日
* 创建时间:下午10:09:29
* 创建用户:yellowcong
* 机能概要:验证码比对
* @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 map = new HashMap();
//验证是否对,不管大小写
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();
}
}
}
我们创建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
* 创建时间:8:38:31
* 创建用户:yellowcong
* 机能概要:自定义控制器
*/
@Configuration("captchaConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CaptchaConfiguration {
// 注册bean到spring容器
@Bean
@ConditionalOnMissingBean(name = "captchaController")
public CaptchaController captchaController() {
return new CaptchaController();
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yellowcong.auth.conf.CaptchaConfiguration
界面添加了一个验证码表的图片,但是没有通过表单提交的方式提交到后台。界面的搭建,需要大家明白如何引入js资源文件,通过th:src的这种方式
<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>
这个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(""+msg+"");
}else{
$("#code_str").html(""+msg+"");
}
}
// 获取到当前项目的名称
var contextPath = function() {
var path = "/" + location.pathname.split("/")[1];
//当项目的目录是根目录的情况
if(path == "/login"){
return "";
}else{
return path;
}
}
为啥我会把pom.xml单独拿出来说一下,因为一般我们在pom中,还需要添加cas-server-core-configuration
的依赖,不然就会报错,说找不到配置类,这个问题以前也讲过
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-core-configurationartifactId>
<version>${cas.version}version>
<scope>systemscope>
<optional>trueoptional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jarsystemPath>
dependency>
<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.0modelVersion>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-codeartifactId>
<packaging>warpackaging>
<version>1.0version>
<dependencies>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-webapp${app.server}artifactId>
<version>${cas.version}version>
<type>wartype>
<scope>systemscope>
<optional>trueoptional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-webapp-tomcat-${cas.version}.warsystemPath>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-core-webflowartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-core-authenticationartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-webapp-configartifactId>
<version>${cas.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-core-configurationartifactId>
<version>${cas.version}version>
<scope>systemscope>
<optional>trueoptional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jarsystemPath>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.21version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>org.jboss.marshallinggroupId>
<artifactId>jboss-marshalling-osgiartifactId>
<version>1.4.10.Finalversion>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>com.rimerosolutions.maven.pluginsgroupId>
<artifactId>wrapper-maven-pluginartifactId>
<version>0.0.4version>
<configuration>
<verifyDownload>trueverifyDownload>
<checksumAlgorithm>MD5checksumAlgorithm>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>${springboot.version}version>
<configuration>
<mainClass>${mainClassName}mainClass>
<addResources>trueaddResources>
<executable>${isExecutable}executable>
<layout>WARlayout>
configuration>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>2.10version>
<executions>
<execution>
<id>copy-dependenciesid>
<phase>compilephase>
<goals>
<goal>copy-dependenciesgoal>
goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/liboutputDirectory>
<includeScope>systemincludeScope>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-war-pluginartifactId>
<version>3.1.0version>
<configuration>
<warName>caswarName>
<failOnMissingWebXml>falsefailOnMissingWebXml>
<recompressZippedFiles>falserecompressZippedFiles>
<archive>
<compress>falsecompress>
<manifestFile>${manifestFileToUse}manifestFile>
archive>
<overlays>
<overlay>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-webapp${app.server}artifactId>
overlay>
overlays>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.3version>
plugin>
plugins>
<finalName>casfinalName>
build>
<properties>
<cas.version>5.2.1cas.version>
<springboot.version>1.5.8.RELEASEspringboot.version>
<app.server>-tomcatapp.server>
<mainClassName>org.springframework.boot.loader.WarLaunchermainClassName>
<isExecutable>falseisExecutable>
<manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MFmanifestFileToUse>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<repositories>
<repository>
<id>sonatype-releasesid>
<url>http://oss.sonatype.org/content/repositories/releases/url>
<snapshots>
<enabled>falseenabled>
snapshots>
<releases>
<enabled>trueenabled>
releases>
repository>
<repository>
<id>sonatype-snapshotsid>
<url>https://oss.sonatype.org/content/repositories/snapshots/url>
<snapshots>
<enabled>trueenabled>
snapshots>
<releases>
<enabled>falseenabled>
releases>
repository>
<repository>
<id>shibboleth-releasesid>
<url>https://build.shibboleth.net/nexus/content/repositories/releasesurl>
repository>
repositories>
<profiles>
<profile>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
<id>execid>
<properties>
<mainClassName>org.apereo.cas.web.CasWebApplicationmainClassName>
<isExecutable>trueisExecutable>
<manifestFileToUse>manifestFileToUse>
properties>
<build>
<plugins>
<plugin>
<groupId>com.soebes.maven.pluginsgroupId>
<artifactId>echo-maven-pluginartifactId>
<version>0.3.0version>
<executions>
<execution>
<phase>prepare-packagephase>
<goals>
<goal>echogoal>
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>falseactiveByDefault>
activation>
<id>pgpid>
<build>
<plugins>
<plugin>
<groupId>com.github.s4u.pluginsgroupId>
<artifactId>pgpverify-maven-pluginartifactId>
<version>1.1.0version>
<executions>
<execution>
<goals>
<goal>checkgoal>
goals>
execution>
executions>
<configuration>
<pgpKeyServer>hkp://pool.sks-keyservers.netpgpKeyServer>
<pgpKeysCachePath>${settings.localRepository}/pgpkeys-cachepgpKeysCachePath>
<scope>testscope>
<verifyPomFiles>trueverifyPomFiles>
<failNoSignature>falsefailNoSignature>
configuration>
plugin>
plugins>
build>
profile>
profiles>
project>
这个地方做的是验证码的功能,具体更加严密的逻辑可以你们自己添加,我就实现了部分校验功能
解决办法,单独导入配置cas-server-core-configuration
的依赖包。
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-core-configurationartifactId>
<version>${cas.version}version>
<scope>systemscope>
<optional>trueoptional>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jarsystemPath>
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