我们正在使用API优先方法来构建应用程序,在此过程中,我们仅以REST API为基础开始构建,然后再添加GUI。
现在,我正在尝试将GUI添加到某些模块中,这就是我坚持选择正确的前进方式的地方。
我的Spring Boot Web应用程序中有一个RestController
方法来创建用户
@PostMapping(value={"/rest/admin/users", "/ajax/admin/users"})
@ApiOperation(value="Create a user", produces="application/json", consumes="application/json")
public ResponseEntity<User> create(@RequestBody User user) {
User createdUser = this.userService.add(user);
URI location = CommonFunctions.buildResourceLocation("/{id}", createdUser.getId());
return ResponseEntity.created(location).body(createdUser);
}
我们的REST API使用基本身份验证进行保护,并且这些API可以完美运行而没有任何问题。
这里要注意的是:
/rest/admin/users
以及/ajax/admin/users
(/rest
指示REST调用,/ajax
指示来自UI的AJAX调用)访问该方法。这是可以接受的方法吗?/rest
URL进行的任何呼叫都必须具有基本身份验证标头,而/ajax
的呼叫不受基本身份验证的保护。他们采用普通形式的登录身份验证。在这种情况下,它们只需要X-CSRF
标头。现在,为了减少我们必须编写的代码,我只想重新使用上述REST控制器方法来通过Ajax创建用户。
在我的JSP中,我的表单类似于以下表单:
<form:form action="/ajax/admin/users" modelAttribute="user" id="user_create_form">
<label for="name">Full Name</label>
<input type='text' id='name' name='name' placeholder='' class='form-control focus-on-load'/>
<label for="email">E-Mail Address</label>
<input type='text' id='email' name='email' placeholder='' class='form-control'/>
<label for="role">Role</label>
<select class='form-control short' name='role.id' id='role'>
<option value='2'>User</option>
<option value='1'>Site Administrator</option>
</select>
</form:form>
单击“保存”按钮时,我正在对表单数据进行序列化,以便获得如下所示的JSON:
{
"name":"User Full Name",
"email":"useremail@somedomain.com",
"role":{
"id":1
}
}
要序列化,我使用以下代码:
var formData = getFormData($form);
我从here得到了getFormData($form)
的逻辑
这是我的AJAX电话
$.ajax({
url:$form.attr('action'),
method:'POST',
dataType:'json',
contentType:'application/json',
data:JSON.stringify(formData),
beforeSend:function(xhr) {
if (header && token) {
xhr.setRequestHeader(header, token);
}
},
success:function(result) {
//Do something to indicate success
}, error: function(xhr, textStatus, errorThrown) {
//Do something to indicate failure
}
});
在这里,除了序列化之外,一切都正常。当我序列化表单数据时,这就是我得到的
{
"name":"SOme Name",
"email":"someemail@org.com",
"role.id":1
}
相对
{
"name":"Some Name",
"email":"someemail@org.com",
"role":{"id":1}
}
这是阻止我重新使用REST控制器方法处理AJAX请求的唯一方法。 GET请求可以正常工作而不会出现问题。
虽然我知道可以在触发AJAX调用之前生成自定义JSON对象,但我希望有一个通用的解决方案,因为屏幕很多,而且我希望尽可能避免出错。
这里更大的问题是,是否建议对AJAx请求重新使用REST控制器(前提是两者都具有不同的身份验证领域/方案)?如果是这样,我是否遵循正确的方法?
谢谢, 斯里拉姆
答案 0 :(得分:0)
- 您使用的是同一个API,一个请求具有验证,而另一个请求没有验证(不推荐)。
在第一件事中,您定义要出于两个不同目的而重复使用同一方法。
我认为您尝试实现的目标实际上违反了REST-API标准。
因此,建议您使用两种不同的方法(两个具有不同方法的不同url)来重写此api,其中一个/ajax/admin/users
必须在匿名打开的url中列出,而/rest/admin/users
必须是安全的。>
据我所知,csrf
令牌在春季安全性中用于验证客户端...。因此,您必须在每次请求时发送令牌以在门户上验证/验证用户。
- 现在来到第二点...(ajax调用序列化)
据我所知,您的html表单结构是扁平的(都在相同的层次结构级别上)
<label for="name">Full Name</label>
<input type='text' id='name' name='name' placeholder='' class='form-control focus-on-load'/>
<label for="email">E-Mail Address</label>
<input type='text' id='email' name='email' placeholder='' class='form-control'/>
<label for="role">Role</label>
<select class='form-control short' name='role.id' id='role'>
<option value='2'>User</option>
<option value='1'>Site Administrator</option>
</select>
如果看到选择的名称为role.id
,并且html元素的存在形式平行。
因此,默认标准json将由ajax序列化生成,将是像
{
"name":"SOme Name",
"email":"someemail@org.com",
"role.id":1
}
建议您编写自己的自定义方法来根据需要更改对象结构。
谢谢...