能否实现一个自己验证安全性的接口给第三方来上传文件到后台。一次调用的HTTP接口(每次带身份信息),不需要每次获取token的那种。能给个思路吗?
CUBA 还是 Jmix?
CUBA里面,谢谢
你好,
考虑以下实现方式
-
自定义Servlet
用这种方式的话可以直接将接口定义在 core层,可以省去 web->core的调用过程。但这种方式动作稍大一点,需要自己实现一个 Servlet,自己实现接收文件的 controller,处理安全上下文 -
基于 RestAPI 文件上传接口
这种方式还是使用现有的 RestAPI 文件上传接口。添加一个自定义Filter,来构建安全上下文。但是 REST API 的安全机制是通过 XML 配置的,大概看了一下,没有提供扩展的机制。只能使用这个文档 介绍的方式来添加自定义Filter 。 -
扩展 RestAPI 服务
参考这里:https://doc.cuba-platform.cn/restapi-7.2-chs/rest_api_v2_custom_controllers.html
但是有几个配置可以简化一下,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security">
<!-- 在这个包下面定义接收文件的控制器-->
<context:component-scan base-package="com.company.test.portal.myapi"/>
<security:http pattern="/rest/myapi/**"
create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<!- 这里将 access 配置为 permitAll,就是不进行身份验证-->
<intercept-url pattern="/rest/myapi/**" access="permitAll"/>
<anonymous enabled="false"/>
<csrf disabled="true"/>
<cors configuration-source-ref="cuba_RestCorsSource"/>
<custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER"/>
</security:http>
</beans>
以上三种方式,可以先试试第三种。有具体问题再沟通。
感谢答复,我现在是这样干的。我在WEB模块里自定义了一个Spring的RestController来接收文件上传,然后我调用了authenticationService.login来做登录验证,发现SecurityContext没有被设置到上下文,然后手动设置了,不知道这样处理是否正确,有没有什么安全隐患。
有点类似您提到的第一个方案,是否应该移到core层?
Credentials lp = new LoginPasswordCredentials(username, password);
AuthenticationDetails authenticationDetails = authenticationService.login(lp);
AppContext.setSecurityContext(new SecurityContext(authenticationDetails.getSession()));
这里你使用匿名会话就行了。刚才再看了一下,可以更简单:
扩展并覆盖 RestAPI 提供的 CubaAnonymousAuthenticationFilter :
public class ExCubaAnonymousAuthenticationFilter extends CubaAnonymousAuthenticationFilter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 在这里根据需要来构建一个匿名安全下文,可以根据 request url 业判断 ,也可以根据自定义的安全规则来判断,比如检测特定的 header、 ip地址等。
if(xxxxxxx){
populateSecurityContextWithAnonymousSession();
chain.doFilter(request,response);
}else{
super.doFilter(request, response, chain);
}
}
}
然后在 rest-dispatcher-spring.xml
文件中注册扩展的 bean :
<bean id="cuba_AnonymousAuthenticationFilter"
class="xx.xx..ExCubaAnonymousAuthenticationFilter"/>
这种方式就是我上面说的第二种方式,不用再写控制器接收文件。完全利用 RestAPI 的文件上传接口。
感谢回答,不知道RESTAPI是用的何种方式上传文件的,如果是AJAX的方法,那应该没法传较大的文件吧?大文件用Multipart比较合适点?
Ajax 与 Multipart 是不同的概念。Ajax 指的是调用方式,Multipart 指的传输编码方式。CUBA RestAPI 支持使用 multipart/form-data 格式。
参考 RestAPI 文件上传文档:
https://doc.cuba-platform.cn/restapi-7.2-chs/rest_api_v2_ex_file_upload.html
我意思是我看例子是用ajax方式提交的,ajax方式是不支持multipart/form-data方式吧?有用multipart/form-data提交的例子么?
现代浏览器基本都支持,因为有了 FormData 。具体可以百度一下。
您的意思就是说我用例子里的方式上传一个大文件(1GB),后台处理也可以采用流的方式来处理,不至于占用大量内存。是这样意思吗?我一直以为用ajax上传,是把文件读出来之后转成base64传递的,大文件会爆内存。
是的。是流式处理的。在浏览器支持 FormData 前也不需要base64编码,那时通用的处理方式是自动构建一个 form表单 ,然后提交。
谢谢答复!