spring boot / spring安全性是从javascript忽略/登录调用 [英] spring boot / spring security is ignoring /login call from javascript
问题描述
我正在使用Spring-Boot 1.1.7,带有spring security,html(没有百里香叶)和javascript。当我使用javascript提交登录信息时,我无法使登录正常工作。当我使用带有表单的html时,spring-security接收请求,进行身份验证并愉快地继续进行。但是使用Javascript,我得到302重定向而没有身份验证。
I am using Spring-Boot 1.1.7, with spring security, html (no thyme-leaf) and javascript. I am unable to get my login to work correctly when I use javascript to submit my login. When I use html with a form, spring-security picks up the requests, authenticates and proceeds happily. But with Javascript, I get a 302 redirect and no authentication.
这是我的配置:
@ComponentScan
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MyApplication {
public static void main(String[] args) {
ApplicationContext edm = SpringApplication.run( MyApplication.class, args );
}
}
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/menu").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/fonts/**").permitAll()
.antMatchers("/libs/**").permitAll();
http
.formLogin().failureUrl("/login?error")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.permitAll();
http
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired")
.maxSessionsPreventsLogin(true)
.and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/");
http
.authorizeRequests().anyRequest().authenticated();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService( customUserDetailsService ).passwordEncoder( encoder );
}
@Override
public void configure(WebSecurity security){
security.ignoring().antMatchers("/css/**","/fonts/**","/libs/**");
}
}
我有自己的UserDetailsService
And I have my own UserDetailsService
@Component
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userService.findByUsername( userName );
if ( user == null ) {
throw new UsernameNotFoundException( "UserName " + userName + " not found" );
}
return user;
}
}
最后,这里是提交帖子的javascript :
And finally, here is the javascript that submits the post:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$("#login").click(function(){
username=$("#username").val();
password=$("#password").val();
$.ajax({
type: "POST",
url: "/login",
beforeSend: function(xhr){
xhr.setRequestHeader(header, token);
},
data: "username="+username+"&password="+password,
success: function(html){
alert("logged in");
}
});
return false;
});
如果我从网址/登录进行此调用,我会获得弹簧提供的登录表单并且所有工作完美。但我需要使用javascript,所以我想知道是否有什么不同我需要做的告诉Spring寻找它?
If I make this call from the url /login, I get the spring provided login form and all works perfectly. but I have a need to use javascript so I am wondering if there is something different I need to do to tell spring to look for it?
推荐答案
以下是适合我的答案/解决方案。基于这篇文章( http://patrickgrimard.com/2014/01/03/spring-security-csrf-protection-in-a-backbone-single-page-app/ ),添加 CSRFTokenGeneratorFilter扩展OncePerRequestFilter
并将其连接到我的安全配置,允许使用我提供的javascript参数。
Here is the answer/solution that worked for me. Based on this article (http://patrickgrimard.com/2014/01/03/spring-security-csrf-protection-in-a-backbone-single-page-app/), adding a CSRFTokenGeneratorFilter extends OncePerRequestFilter
and wiring it up to my security config, allowed my javascript provided parameters to be used.
public final class CSRFTokenGeneratorFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
response.setHeader("X-CSRF-HEADER", token.getHeaderName());
response.setHeader("X-CSRF-PARAM", token.getParameterName());
response.setHeader("X-CSRF-TOKEN", token.getToken());
filterChain.doFilter(request, response);
}
}
连线如下:
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
..}
}
我不确定为什么需要过滤器,但我认为spring-boot / security不会将其用作默认。
I am not sure why the filter is needed, but I guess spring-boot/security doesn't use that as a default.
这篇关于spring boot / spring安全性是从javascript忽略/登录调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!