场景:

Spring Boot中使用Spring Security,前端登录使用Ajax提交表单,但总是报403,请求总被拒绝.

原因:

spring security默认开启了Cross Site Request Forgery (CSRF)。
当ajax post提交遇到403时,应当时缺少了csrf。

解决办法

  • 第一种方法: 可以禁用在SecurityConfig中禁用csrf
  • 第二种方法:form中补全csrf,并修改Ajax的url地址
  • 在form表单中添加隐藏域csrf
    <input type="hidden"
    	name="${_csrf.parameterName}"
    	value="${_csrf.token}"/>
    <input type="button" onclick="login()" value="登陆">
    完整表单如下:
    <form th:action="@{/login}" method="post">
    	用户名:<input id="uname" name="uname"/><br>
    	密码:<input id="pwd" name="pwd"><br/>
    	记住我 <input type="checkbox" name="remember">
    	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    	<input type="button" onclick="login()" value="登陆">
    </form>
    修改Ajax的url地址
    $.ajax({
    	type:"POST",
    	url:"[[@{/login}]]?[(${_csrf.parameterName})]=[(${_csrf.token})]",
    	data:{
    		"uname":name,
    		"pwd":password
    	},
    	success:function (json) {
    		console.log(JSON.stringify(json));
    	},
    	error:function (e) {
    		alert(e.responseText);
    	}
    });
    head中添加
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
    js文件中添加
     var token = $("meta[name='_csrf']").attr("content");
     var header = $("meta[name='_csrf_header']").attr("content");
     $(document).ajaxSend(function(e, xhr, options) {
         xhr.setRequestHeader(header, token);
     });

    完整代码

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta charset="UTF-8">
    	<title>武林秘籍管理系统</title>
    	<meta name="_csrf" th:content="${_csrf.token}"/>
    	<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
    </head>
    <body>
    	<h1 align="center">欢迎登陆武林秘籍管理系统</h1>
    	<hr>
    	<div align="center">
    		<form th:action="@{/login}" method="post">
    			用户名:<input id="uname" name="uname"/><br>
    			密码:<input id="pwd" name="pwd"><br/>
    			记住我 <input type="checkbox" name="remember">
    			<input type="hidden"
    				   name="${_csrf.parameterName}"
    				   value="${_csrf.token}"/>
    			<input type="button" onclick="login()" value="登陆">
    		</form>
    	</div>
    </body>
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <script>
    	function login() {
    		var name = $("#uname").val();
    		var password = $("#pwd").val();
    		if (name===""||password===""){
    			alert("用户名和密码不能为空!");
    		}
    		var token = $("meta[name='_csrf']").attr("content");
    		var header = $("meta[name='_csrf_header']").attr("content");
    		$(document).ajaxSend(function(e, xhr, options) {
    			xhr.setRequestHeader(header, token);
    		});
    		$.ajax({
    			type:"POST",
    			url:"[[@{/login}]]?[(${_csrf.parameterName})]=[(${_csrf.token})]",
    			data:{
    				"uname":name,
    				"pwd":password
    			},
    			success:function (json) {
    				var obj = JSON.stringify(json);
    				console.log(obj);
    				if (json['code'] === "login_ok"){
    					location.href="/";
    				}
    			},
    			error:function (e) {
    				alert(e.responseText);
    			}
    		});
    	}
    </script>
    </html>
    最后修改日期:2020-01-16

    作者

    留言

    撰写回覆或留言

    发布留言必须填写的电子邮件地址不会公开。