这是我的spring-security.xml:
<security:http pattern="/eklienci/**"
authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint"
create-session="stateless">
<security:intercept-url pattern="/eklienci/**"
access="hasAnyAuthority('ADMIN','USER','VIEWER')" />
<form-login
authentication-success-handler-ref="mySuccessHandler"
authentication-failure-handler-ref="myFailureHandler"
/>
<security:custom-filter ref="restServicesFilter"
before="PRE_AUTH_FILTER" />
</security:http>
<!-- other stuff --!>
<beans:bean id="restAuthenticationEntryPoint"
class="pl.aemon.smom.config.RestAuthenticationEntryPoint" />
<!-- Filter for REST services. -->
<beans:bean id="restServicesFilter"
class="pl.aemon.smom.config.RestUsernamePasswordAuthenticationFilter">
<beans:property name="postOnly" value="true" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler" ref="mySuccessHandler" />
</beans:bean>
这是我的RestUsernamePasswordAuthenticationFilter:
public class RestUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
{
@Autowired
private CustomAuthenticationProvider authenticationProvider;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
Enumeration<String> names = request.getHeaderNames();
while(names.hasMoreElements())
{
System.out.println(names.nextElement());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
System.out.println("Username " + username + " password: " + password);
if(username!=null)
{
username = username.trim();
}
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return authenticationProvider.authenticateRest(authRequest);
// System.out.println(auth.toString());
// return auth;
}
@Override
protected String obtainPassword(HttpServletRequest request) {
return request.getHeader("password");
}
@Override
protected String obtainUsername(HttpServletRequest request) {
return request.getHeader("username");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
Authentication auth = attemptAuthentication(httpRequest, httpResponse);
SecurityContextHolder.getContext().setAuthentication(auth);
chain.doFilter(request, response);
}
}
这是我的RestController方法
@RestController
@RequestMapping("/eklienci")
public class EklientRestController
{
@RequestMapping(value="/get/{eklientid}")
public Eklient get(@PathVariable String eklientid)
{
return userService.findById(eklientid);
}
@RequestMapping(value = "/add", method = RequestMethod.POST, produces="application/json", consumes="application/json")
@ResponseBody
public String add(@RequestBody String json)
{
System.out.println(json);
Eklient pj = new Eklient();
ObjectMapper mapper = new ObjectMapper();
try
{
pj = mapper.readValue(json, Eklient.class);
return mapper.writeValueAsString(pj);
} catch (JsonParseException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return "Error";
}
}
当我尝试调用/ get / {eklientid}时,它总能正常工作。所有GET调用总是至少返回关于UNARTHORIZED访问的信息(401),我看到来自RestUsernamePasswordAuthenticationFilter的日志。
但是当我尝试任何POST调用时(例如/ eklienci / add}我的应用程序总是返回403代码并且不生成任何日志。原因是什么?如何解决?
答案 0 :(得分:3)
CSRF。您可以(暂时!)关闭security.xml中的CSRF以确认问题。主要是您需要将CSRF headers添加到REST调用和<sec:csrfInput/>
JSP标记中以进行任何客户端 - 服务器调用。仅供参考,我需要在我的开源项目中实现的其他类,可能对您有用:
答案 1 :(得分:-2)
关闭CSRF保护。如果您有create-session="stateless"
,则不需要它。
<security:http ...>
<security:csrf disabled="true"/>
<!-- the rest same as before -->
</security:http>