我必须向我的 restful 服务发出 HTTP.Post(Android 应用程序),以注册新用户!
问题是,当我尝试向注册端点(没有安全性)发出请求时,Spring 一直阻止我!
我的项目依赖
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.1.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
<jackson.version>1.9.10</jackson.version>
<spring.security.version>4.0.2.RELEASE</spring.security.version>
<hibernate.version>4.2.11.Final</hibernate.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
</properties>
Spring 安全
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!--this is the register endpoint-->
<http security="none" pattern="/webapi/cadastro**"/>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/webapi/dados**"
access="hasAnyRole('ROLE_USER','ROLE_SYS')" />
<intercept-url pattern="/webapi/system**"
access="hasRole('ROLE_SYS')" />
<!-- <access-denied-handler error-page="/negado" /> -->
<form-login login-page="/home/" default-target-url="/webapi/"
authentication-failure-url="/home?error" username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/home?logout" />
<csrf token-repository-ref="csrfTokenRepository" />
</http>
<authentication-manager>
<authentication-provider>
<password-encoder hash="md5" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT username, password, ativo
FROM usuarios
WHERE username = ?"
authorities-by-username-query="SELECT u.username, r.role
FROM usuarios_roles r, usuarios u
WHERE u.id = r.usuario_id
AND u.username = ?" />
</authentication-provider>
</authentication-manager>
<beans:bean id="csrfTokenRepository"
class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
<beans:property name="headerName" value="X-XSRF-TOKEN" />
</beans:bean>
</beans:beans>
Controller
@RestController
@RequestMapping(value="/webapi/cadastro", produces="application/json")
public class CadastroController {
@Autowired
UsuarioService usuarioService;
Usuario u = new Usuario();
@RequestMapping(value="/novo",method=RequestMethod.POST)
public String register() {
// this.usuarioService.insert(usuario);
// usuario.setPassword(HashMD5.criptar(usuario.getPassword()));
return "teste";
}
}
JS 发布( Angular )
$http.post('/webapi/cadastro/novo').success(function(data) {
alert('ok');
}).error(function(data) {
alert(data);
});
错误
HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'
--- 解决方案 ---
实现过滤器以将我的 X-XSRF-TOKEN 附加到每个请求 header
public class CsrfHeaderFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
将此过滤器的映射添加到 web.xml 并完成!
最佳答案
在你上面的代码中,我看不到将 CSRF token 传递给客户端的东西(如果你使用 JSP 等,这是自动的)。
一个流行的做法是编写一个过滤器以将 CSRF token 附加为 cookie。然后您的客户端首先发送一个 GET 请求来获取该 cookie。对于后续请求,该 cookie 将作为 header 发回。
而官方Spring Angular guide详细解释,可以引用Spring Lemon一个完整的工作示例。
要将 cookie 作为 header 发回,您可能需要编写一些代码。默认情况下,AngularJS 会这样做(除非您发送跨域请求),但这里有一个示例,如果您的客户不这样做的话,它会有所帮助:
angular.module('appBoot')
.factory('XSRFInterceptor', function ($cookies, $log) {
var XSRFInterceptor = {
request: function(config) {
var token = $cookies.get('XSRF-TOKEN');
if (token) {
config.headers['X-XSRF-TOKEN'] = token;
$log.info("X-XSRF-TOKEN: " + token);
}
return config;
}
};
return XSRFInterceptor;
});
angular.module('appBoot', ['ngCookies', 'ngMessages', 'ui.bootstrap', 'vcRecaptcha'])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
$httpProvider.interceptors.push('XSRFInterceptor');
}]);
关于java - HTTP 状态 403 - 在请求参数中发现无效的 CSRF token 'null',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31978464/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳