一个不错的基于Spring boot+Security+Redis+MySql实现权限登录和反爬虫的脚手架

介绍

一个基于Spring boot 2.4.2、JDK 1.8、Security、防恶意请求技术实现的前后端分离的脚手架,可以为开发人员省去前期框架调研和搭建的成本。源码在码云上。

软件架构

  1. Spring boot 2.4.2
  2. JDK 1.8
  3. Security
  4. kk-anti-reptile(反爬虫接口防刷组件)
  5. Redis(登录用户信息)
  6. MySQL
  7. MyBatis

安装教程

  1. 克隆 本代码到本地
  2. 修改application.yml配置,包含Mysql数据库信息、Redis连接信息、kk-anti-reptile配置信息(不修改也可以,默认,详细参数见:kk-anti-reptile
  3. 将项目other/SQL/中的脚本放到mysql中执行,初始化表结构
  4. 启动项目
  5. 使用测试工具或者前端连接请求

使用说明

本示例在TestWebSecurity类中配置了Security前端登录接口和退出登录接口,如想自定义接口,请修改如下图圈中的配置

application.yml 配置文件中kk-anti-reptile 部分配置如下:

# 恶意请求
anti:
  reptile:
    manager:
    # 激活恶意请求/反爬虫配置
      enabled: true
    # 需要拦截的请求,多个以“,”分隔,或者直接在controller方法上添加@AntiReptile
    #  include-urls: ^/admin/.*$
      ua-rule:
      #允许linux系统访问
        allowed-linux: true
        # 全局拦截,默认为false,为false时,需要配置上面的include-urls
      global-filter-mode: true

详细参数请参见kk-anti-reptile

请求示例

登录接口

请求链接

http://localhost:8099/auth/login

请求参数

username:admin password:1234

注意,此处需要使用表单提交,postman中如下:

响应参数

登录成功返回参数如下:

{
    "code": "00000",
    "msg": "操作成功!",
    "data": {
        "token": "3aa72e4a-74b5-4542-9e56-e7f31ec5ce09",
        "permissions": [],
        "loginTime": 1611284216123
    }
}

其中,token的值就是前端需要在每次请求中在请求头部传递到后端的参数

退出登录接口

请求链接

http://localhost:8099/auth/logout

请求参数

请求头部需要放置如下参数:

X-token:token的值

Postman中如下:

响应参数

{
    "code": "00000",
    "msg": "您已经退出登录!"
}

正常接口

正常业务逻辑中调用的接口传参

请求链接

http://localhost:8099/test/listOrientations

请求参数

header中必须带有X-token参数,其他业务参数请写在请求体中

Postman中如下:

正常响应参数(没有超过反爬虫预警)

{
    "code": "00000",
    "msg": "ddd"
}

被拦截的响应参数

当使用postman多次请求,请求超过阈值,将会返回验证码页面(如果前端JQ请求,请参照kk-anti-reptile处理方式正常显示验证码)




	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
	<title>kk-anti-reptile验证</title>
	<script>
		function getXhr() {
            var xhr = null;
            try {
                xhr = new XMLHttpRequest();
            } catch (e) {
                try {
                    xhr = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");
                }
            }
            return xhr;
        }

        function refresh() {
            var xhr = getXhr();
            var verifyId = document.getElementById("verifyId").value;
            var baseUrl = document.getElementById("baseUrl").value;
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var verifyObj = JSON.parse(xhr.responseText);
                    document.getElementById("verifyId").value = verifyObj.verifyId;
                    document.getElementById("verifyImg").src = verifyObj.verifyImgStr;
                }
            }
            xhr.open("POST", baseUrl + "/kk-anti-reptile/refresh?verifyId="+verifyId, "true");
            xhr.send();
        }

        function validate() {
            var elements = document.getElementById("verifyFrom");
            var formData = new FormData();
            for(var i = 0; i < elements.length; i++) {
                formData.append(elements[i].name, elements[i].value);
            }
            var baseUrl = document.getElementById("baseUrl").value;
            var xhr = getXhr();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var obj = JSON.parse(xhr.responseText);
                    if (obj.result == true) {
                        closeThisWindows();
                    } else {
                        alert("验证码填写错误")
                    }
                }
            }
            xhr.open("POST", baseUrl + "/kk-anti-reptile/validate", "true");
            xhr.send(formData);
        }

        function closeThisWindows() {
            if (navigator.userAgent.indexOf("MSIE") > 0) {
                if (navigator.userAgent.indexOf("MSIE 6.0") > 0) {
                    window.opener = null;
                    window.close();
                } else {
                    window.open('', '_top');
                    window.top.close();
                }
            } else if (navigator.userAgent.indexOf("Firefox") > 0) {
                window.location.href = 'about:blank';
            } else if (navigator.userAgent.indexOf("AppleWebKit") > 0) {
                window.location.href = 'about:blank';
                window.close();
            } else {
                window.opener = null;
                window.open('', '_self', '');
                window.close();
            }
        }
	</script>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
	<title>普通验证码</title>

	<style>
		* {
			box-sizing: border-box;
			margin: 0;
			padding: 0;
		}

		form {
			width: 240px;
			margin: 100px auto;
			padding: 20px;
		}

		input[type="text"] {
			margin: 10px 0;
			padding: 0 4px;
			width: 100%;
			height: 32px;
			border: 1px solid #c3c3c3;
			border-radius: 4px;
		}

		input[type="button"] {
			width: 100%;
			height: 32px;
			color: #fff;
			background-color: #40a9ff;
			border-color: #40a9ff;
			border-radius: 4px;
			outline: 0;
			cursor: pointer;
			text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
			box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
			border-style: none;
		}

		.img-wrapper {
			display: flex;
			align-items: center;
		}

		.img-wrapper img {
			width: 130px;
			height: 48px;
		}

		.img-wrapper a {
			text-decoration: none;
			color: #1890ff;
		}
	</style>




	<form id="verifyFrom" method="post" action="">
		<input type="hidden" id="baseUrl" name="baseUrl">
		<input type="hidden" id="verifyId" name="verifyId" value="d4eee0b1-b416-4231-96d8-8af6f70ad2c2">
		<input type="hidden" id="realRequestUri" name="realRequestUri" value="/test/listOrientations">
		<span>操作频繁,请输入验证码</span>
		<div class="img-wrapper">
			<img id="verifyImg" src="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAAwCAIAAABSYzXUAAAKmUlEQVR42u2cC2yVZxnHmzQ6x8RpYtTMazSOLZuJi9FhZowa57zh3HQumXPOazRTzOKVBadGwrpCy4QxLmVcymUUaMso13Ir0FLAstJyWcu1W2GspbVc1q2FwuPvOe/hO5fv9p7Tc2iTnSdfTsg53/d+7/tc/s//ed635ElOhoHk5VSQM0NOcmZwyRsXpaNXP3NmGALVVx2Rf9XKDyvlu8uj173lMq5Glh6SM705M2RfKlrlwZV6leyT2nY53K3RcKxH9rwm85vloVVqj6kNcq4v5ZEvX5G+gZwZLIKACLi/Qpa3SL+PvgYuq21+vkZ+UiXNnb5DvXVJTpyV+lNq1Odekr9vl1+tU/stOZgzQ6D87y0Zu1Gv1y6E34yWiRUga0ubnO2Tl7tk6yvywiEp3iN/3qIWMjj2QKUOOHGnzGuWdcek8XXp6cuZIVCtj29WlfGPAEh5/Q1VJQqd26TK/X653PSsjC5VjaN6DIAZMAYmaelW8+RyQ2oys1H1SEAEQwrqRvX8+8kd+n1lq0ysl7uXBqFTzgxWgs/ivHctUs2GQgrRQEwkSeEuTRUBYZQzQxCk/L5aFY26b58jt5akDynwV2jV2mM5M9ixFDek7DolrV1qDDLtYARm9egaJVFvUzOkxFI8IWVTWwY0CNMlIBpOvw3MANXzhJRBspSn6qVoTwamR8FBnh96M1AfXrqcRTMsPugBKW1nU6tL3cKAYFcaRcakXfL1F2RkkeQXyPWT5FMzNcccPDPUZkBNY5bLT1fLn7YoeQAKVh/VBgAwnVJfDNyY3yw/qJAP/Efe8bRcVyifnim/XKtDuSFl8FmEnEGQpSR4wI3FkveU95VB1mRlhnN9UrRbPeKGyaqvEZNl9AJ5rFoW7pdpDeqzv1mv2jS48aOV+hORiyOT0La9Koe65MybyZoFXkfN8l3hHzZm2AwdvTo3m7LZkaWHfKfnXF9ZfK3MAEZ/aKr3JD7xnKZNR873y9Ee5S2rjsicJsXixzfJw6tkzIpo2xL3+VuNAvQT2+SdhZFBCnxX+Nv1mTdDh3XHFIOBQmYmd8yVZS9L78VoBKOQjzwbmycOmnUzVB0JcQfwpDNsbf0DcuqC7OuQjScU0CbUyYhJ0cffO0UXeX+FUh0CiCC4ZXbkp4n6Wdc+ZNHw163RGX6rLDmOj/XoUOOu3vCZOVk2A7TvfVOiL7t1tgapaUYyD2eWXLh8SoKuowsokdMXpLVbG5kkz1mN8u86tceHr/raR6drXn2iRqbsUftVn1Bwx6L9A1nPDZ+cEZ0D00sSBsEMkBRzAyidXTM4uv7cPLnQn7AknAv+YH4lQlNSx3WF0Qf9yAZAF42VYkWA0v2KY6AZmGZKM1AOrPtdtYLbtL3y4mHZeVLxMHhjID2m5BaqaIbiXWaS738my2ZA+/kR7GaR8DYAavz22C7Vd5ZF55H/dAqYC8iap+4rT2e6VyIdBQZ5ZLXcuUAB4eZZCmtfWiTfXqazginAFyin4Q6E7+Y22d+pYY3zZrZueGxDJnNYXiin3Htapu9V+KYELdmnzKf9vOod7zPzeFehOin32OxSMWnzFDpKQ4AjVIm6n2/S2o1pEFLgFZXtz9Yo+4LsrjmqHBomTaEHqx4TcRo+v1Emtz8vBfXpM2zkeE/U/GYVN00LT40ZMAM4yArxL+A7qQ3gKBSsYElgOoECTQoWJ4YMIoE/uBVADMJSGRF//9whXW8GVcIU0i3dHpR6XI1uW1LlJQlxgLWIifXH5YulMrY6TYZN+DJJpXYFUQYBW331XPYJK6rHzQnA+CIFfwSL4Q9Gm7A6MrZEtgy5k1VtOB70Pof7op3x27zZF7wAj3bLljadj19GYWKoEoUGBOXUBt3zSYNhlx6IzHxiwjzvXaHlfXbNQBwwD6rceHdws9Xa9uQGJAsIiInrr1JVECOYClcmplPMjFIWHgjJ/5gBXfsJcMqi8PeUGPYz/1W2NrJY3lOsVHtkYl1N2b+jXVq6NH1euZJRM+BQYFFSA4tiLf71FNWe6GF2bv1cMj+uXoMysTy824Q/oy06oMzY/HpjcQLsNndqfgqFchPBAQdbknbfUmpxMzLwC4WFI3x2bmwhYIPBt/vKrRj2QAQn47/0NgP5FvSMxyI0le+qeLnNLbyDPOH5U7wZQB5PFg8zdixBnnCEhcHTQoW3owhUFhAxoXvRbtkUwcNNiXsV9yyNzvORKh2NPAGdCWDYIB533l0md5bKXQvla0uUQWAt7JHn2VPE72rbvYlTzSux13N53obL8HpPFuuA0oyXfNdc3hK95wvzY1/iFisPW6kMEhWfADwXmN7JjCRp6ojxpWCGTc6n2iCXwEHQzI+r9POri+WOefLxGTJqtpcZqA9Ct0ceqIzOAObjKTiCp0s6Kbr3YhA0m3uwmSN4hmUNbJwgeP6ZOqdkWUhjS2J0Ql0CGDIHGHPdyUiZ7H4G5of9gwV8dGsqXsjtf9wcRFhDUlbi8pj9PWXS2GGF6eRhcMDm3CNFNW7ueWoPLuCc2vN7qae7eApFzF+2BnmGhxmYWa1FTy3YEVgJvuYW8NE8GN+adacHhw0zDk6EOj44Vc+noF+GJUlAxgJYln0z1Zxh/ccOHTb+DOuIySEdF4QcYO758qKQ2guVBgNgnjt8bDqRJ8+HwKLpaLqJDQhrHqRq85O5TdF7bp6tGgE9qFRIaEQD1RkuQgJEawFNcstocJvEOdH96OroULzXr+/pAOy0hqBhSVTxvN/KDEZ9777aakfdngInMzdAAFLt739sevRZ3NAt0FaHGX9vRcwhknIDQBFghtDcECpU3Q6pwxLwHyeF4ArwQGom8+ttJUF7hdxsE5re0eAUyZ747jAZP6YUEA3IkoNXe4IF8uT2GDqhWeLAsQG+Fq9KT6YEpmMeU8bbMyVLQdehu2+AQdLb3Vt4Yy12Er1zQ9HuhF2w/Z1RtgpF+/W62E8PvRhEVzxzgxGnPel3Udk1Jh5CKfKpGyZEtigcg4XWDSkJHuPsuLgvCthQ9GZ6Nk1MX6bkUFK/a/SChE0IS6YUU+vu2MZD0nVDkdafSeJXRZMD+B6rW1bRqcq5Pq0cgQdzMoM5j5qlLJb6yUYguzYH1Hzrhr5L2i3xswHVYIANAuqGeKHsHL9NzQnhY4Wsk9WSDwrqvVm8X08J9CCN2/SUrrEwZ5DZptwJqaIbTqsxsD/ElIvsigF2nrQqoDrScskA9/HrsDJVnrLpsF5jOWO9AW7bU0rJBciQfj2lYMEDmLd7zyB4v4H7v1mmFYnnfsMQiv1xkBQ6rJYS3GEd5Lzjd9+gKGb3bUajniJ4uCrN+Bu+0eC532DZDebFtekebAmNBgf0YE2mecn1i7Xy+fl6yGO4ickNNn+Zkhfa3SUmbA6k8ErigLda9kEDcoOlFU3RS9jVn1I4Gp7CckJ3mWQwe9FJ7mm5Fx0q0OVUqQ6OwlPDU2ANNkVM+OFJ3C3+ZAb2AOxwQy54FAzSbG5YnswIFXwHc9ofmIBHcL+Nxw2JoB8bF7E90W3OKTFi/F/TYxtqNKrEDOZGAJBAtj8+U9GqiNQ/MEzNAIPAR0O9Kp2D9ebUXvb+b4kNx9XYh7vD74Qscadni3D4CCgS+udy/wfo2vAEEaPingAAAABJRU5ErkJggg=="> &nbsp;&nbsp;&nbsp;&nbsp;
			<a href="javascript:void(0);" onclick="refresh()">刷新</a>
		</div>
		<input type="text" id="result" name="result">
		<br>
		<input type="button" value="确认" onclick="validate()">
</form>


赞赏我

  1. 如果您觉得这个不错,可以打赏下作者,您的赞同是作者不懈努力的源泉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章