我正在爲我的應用程序編寫客戶端。 Spring堆棧是Spring 4和Spring Security 4(主要部分)。在Spring Security應用程序中使用其餘模板註銷
我嘗試從我通過以下方式申請註銷:
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> entity = new HttpEntity<>("_csrf=" + csrfToken,
httpHeaders);
restTemplate.postForEntity(appUrl + "/logout", entity, String.class);
一個RestTemplate
對象通過以下方式創建(當然登錄前):
new RestTemplate(new HttpComponentsClientHttpRequestFactory())
但我得到的以下例外在服務器上:
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported at
org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:207) at
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:374) at
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:314) at
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:61) at
org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:352)
我得到以下excep當我試圖登錄的應用程序。我設法做的唯一的 方法是獲取登錄頁面並從那裏獲取CSRF令牌。我試圖從以下方式從服務器獲取令牌,並將其返回給客戶端:
@RequestMapping(value = "/api/csrf", method = RequestMethod.GET)
public String csrf(HttpServletRequest httpServletRequest) {
return ((CsrfToken) httpServletRequest.getAttribute(CsrfToken.class.getName())).getToken();
}
但有了這個令牌我得到相同的異常所有的時間。
現在我想至少以任何方式實現註銷,但與RestTemplate
正確登錄相關的筆記也是值得讚賞的。謝謝!
UPDATE:增加安全配置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final DataSource dataSource;
private final UserDetailsService splittingRolesUserDetails;
private final AccessDeniedHandler accessDeniedHandler;
@Autowired
public SecurityConfig(DataSource dataSource, UserDetailsService splittingRolesUserDetails,
AccessDeniedHandler accessDeniedHandler) {
this.dataSource = dataSource;
this.splittingRolesUserDetails = splittingRolesUserDetails;
this.accessDeniedHandler = accessDeniedHandler;
}
// overrides role prefix in case .access() in httpSecurity configuration
// just because it is needed in the task. hasRole() won't work
// as there are used different voters in AffirmativeBased.
// link to the related issue on GitHub:
// https://github.com/spring-projects/spring-security/issues/3701
@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults("");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.authenticationProvider(authenticationProvider())
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select user_name, password, true from user where username=?");
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(splittingRolesUserDetails);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/login/**").permitAll()
.antMatchers("/api/csrf").permitAll()
.antMatchers("/api/ticket/event**").access("hasRole('" + Role.BOOKING_MANAGER.toString() + "')")
.anyRequest().access("hasRole('" + Role.REGISTERED_USER.toString() + "')")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/event")
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.accessDeniedPage("/403")
.and()
.rememberMe()
.userDetailsService(splittingRolesUserDetails);
}
}
當您登錄並且您是如何登錄的,您是否保存了cookie?並且當你請求註銷url時,你是否將cookie添加到頭部?>「當我嘗試登錄應用程序時,我收到以下異常」 – chaoluo
@chaoluo對於登錄,我收到了與註銷相同的異常,我沒有保存cookie。在執行註銷時,我正在設置X-CSRF-TOKEN頭(雖然這裏不需要,據我瞭解),添加「_csrf =」表單參數並設置Content-Type = application/x-www-form-urlencoded。 –
Http是一個無狀態協議,如果你想實現你自己的客戶端,你應該使用cookie(例如JSESSIONID)來請求。但爲什麼不改變客戶端的其他驗證方式(例如HTTP基本/承載驗證)? – chaoluo