对于我的Spring web应用程序,我选择了完整的Java配置,这里没有XML !
应用程序总体运行良好,但我有一些小问题无法说明。
所有的安全GET方法都是允许的,所有的POST方法都是拒绝的。
例如,我有一个JSP,下面有一个表单。如果我使用POST方法,我将重定向到403页面错误。如果我使用GET方法,我传入我的方法"validateCreateStep1"没有任何问题…所以我希望允许任何类型的方法在我的安全区域,而不仅仅是GET !
有人有主意吗?
感谢&看看下面的代码;)
SpringConfiguration.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private LoginService loginService;
@Bean @Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth
.userDetailsService(loginService)
.passwordEncoder(new ShaPasswordEncoder());
}
@Override
public void configure(WebSecurity web)
throws Exception {
web
.ignoring()
.antMatchers(
"/signup",
"/signup/do",
"/static/**"
);
}
@Override
protected void configure(HttpSecurity http)
throws Exception {
http
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/login.do")
.defaultSuccessUrl("/dashboard")
.failureUrl("/?err=1")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/?out=1")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.sessionManagement()
.invalidSessionUrl("/?time=1")
.maximumSessions(1);
}
}
EventController.java
@Controller
@RequestMapping("/event")
@PreAuthorize("hasRole('ROLE_USER')")
public class EventController {
@Autowired
private EventService eventService;
@RequestMapping(value="/create/", method = RequestMethod.GET)
public String prepareCreate(ModelMap model) {
model.addAttribute("eventForm", new EventForm());
return "eventCreate";
}
@RequestMapping(value="/create/validate", method = RequestMethod.POST)
public String validateCreate(ModelMap model, @Valid @ModelAttribute(value="eventForm") EventForm form, BindingResult result, HttpServletRequest request) {
String redirect = null;
if (!result.hasErrors()) {
EventEntity event = eventService.create();
redirect = "dashboard";
} else {
redirect = "eventCreate";
}
return redirect;
}
}
event-create.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" isELIgnored="false" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<div>
<h3>
<spring:message code="event.create.title" />
</h3>
<div>
<c:url value="/event/create/validate" var="formActionURL" />
<form:form method="POST" modelAttribute="eventForm" action="${formActionURL}">
<form:label path="firstname">
<spring:message code="event.create.firstname.label" />
</form:label>
<form:input path="firstname" />
<form:errors path="firstname" cssClass="formFieldError" />
<br />
<form:label path="lastname">
<spring:message code="event.create.lastname.label" />
</form:label>
<form:input path="lastname" />
<form:errors path="lastname" cssClass="formFieldError" />
<br />
<input type="submit" value="<spring:message code="event.create.submit.label" />" />
</form:form>
</div>
</div>
注意,如果禁用CSRF令牌,问题就会消失。
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable()
在这种情况下,POST方法成功了。但如果我没理解错的话,禁用CSRF令牌不太安全,不是吗?例如,我不能只在登录时启用它
在Angular2中,HttpClientXsrfModule模块负责这个。
在拦截器实现的代码中有一个非常有用的注释:
// Skip both non-mutating requests and absolute URLs. // Non-mutating requests don't require a token, and absolute URLs require special handling // anyway as the cookie set // on our origin is not the same as the token expected by another origin. if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') || lcUrl.startsWith('https://')) { return next.handle(req); }
有时,它解释;)