带有 Spring Boot 和 Spring Security 的 Angular2

Posted

技术标签:

【中文标题】带有 Spring Boot 和 Spring Security 的 Angular2【英文标题】:Angular2 with Spring Boot and Spring Security 【发布时间】:2017-07-22 00:17:48 【问题描述】:

首先,我已经检查了this page 的问题并尝试了他的解决方案,但最后我仍然遇到同样的问题。

XMLHttpRequest 无法加载 http://localhost:8080/login。 对预检请求的响应未通过访问控制检查: 请求的资源上不存在“Access-Control-Allow-Origin”标头。 因此,不允许访问 Origin 'http://localhost:3000'。 响应的 HTTP 状态代码为 403。

但是,我到处都放了access-control,所以我不明白为什么会这样。

我的代码是这样的(希望我给你放够了):

在 Angular 中,我的 login.service.ts

check(name: string, password: string): boolean 
     let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Access-Control-Allow-Origin','*');
    let options = new RequestOptions(headers:headers,withCredentials:true);

    if(this.http.post(this.baseUrl, 
        `username=$name&password=$password`,
        headers:headers)
        .toPromise().then(response=> 
          return 
        ))
        return true;    

        return false;
  

如果身份验证成功,我也想返回一个布尔值,但我真的不知道如何知道它是否有效,所以我现在就这样做(而且总是如此)。

然后,在 Java 中,我有以下代码:

@Configuration
@EnableWebMvc
class WebConfig extends WebMvcConfigurerAdapter 

为了安全起见,我得到了这个:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 


    @Autowired
    private RESTLoginSuccessHandler loginSuccessHandler;

    @Autowired
    private RestLogoutSuccessHandler logoutSuccessHandler;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 
        //deactivate CSRF and use custom impl for CORS
        httpSecurity
                .cors.and()
                .csrf().disable()
                .addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
        //authorize, authenticate rest
        httpSecurity
                .authorizeRequests()
                    .anyRequest().hasRole("USER")
                    .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                    .and()
                .formLogin()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .loginPage("/login")
                    .successHandler(loginSuccessHandler)
                    .permitAll()
                    .and()
                .logout()
                    .logoutSuccessHandler(this.logoutSuccessHandler)
                    .permitAll();
    

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
        auth.inMemoryAuthentication().withUser("rano").password("1234").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("USER", "ADMIN");
    


@Bean
CorsConfigurationSource corsConfigurationSource() 
    CorsConfiguration configuration = new CorsConfiguration();

    configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080","http://localhost:3000"));

    configuration.setAllowedMethods(Arrays.asList("PUT","DELETE","POST"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

在我的 LoginSuccessHandler 中:

@Component
public class RESTLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler 

    private RequestCache requestCache = new HttpSessionRequestCache();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            org.springframework.security.core.Authentication authentication) throws IOException, ServletException 

        SavedRequest savedRequest = requestCache.getRequest(request, response);

        if (savedRequest == null) 
            clearAuthenticationAttributes(request);
            return;
        

        String targetUrlParam = getTargetUrlParameter();
        if (isAlwaysUseDefaultTargetUrl()
                || (targetUrlParam != null && StringUtils.hasText(request.getParameter(targetUrlParam)))) 
            requestCache.removeRequest(request, response);
            clearAuthenticationAttributes(request);
            return;
        

        clearAuthenticationAttributes(request);
    

    public void setRequestCache(RequestCache requestCache) 
        this.requestCache = requestCache;
    

那么,您知道问题出在哪里吗?或者如何使用 Spring Boot 和 Spring Security 制作 Angular2 应用程序?因为除了我添加安全性之外,一切都在 Spring Boot 和 Angular 之间工作。

【问题讨论】:

我删除了.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);,但删除了corsConfigurationSource,我在问题中写的就是我在代码中写的。我完全做错了吗? 这次我没有任何 Cors 消息,而是一个新的错误:Unexpected token < in JSON at position 0 我明白你对corsConfigurationSource 的看法,是的,它在我的代码中。但是,对于 Spring Security 日志,启用了 Debug,但在 Java 端我什么也看不到,在 Angular 端我仍然看到 403 错误。但是,当我删除 .addFilter... 时,我不再有这个错误,而是出现了 Unexpected token 的问题。 我在我的问题中添加了我的loginSuccessHandler,但我还决定学习有关 Angular2 和 Java Spring 的 web 应用程序的课程。我希望这样我会看到我做错了什么。也许这是我在其他地方再次做过的事情。如果只是用我的loginSuccesshandler 你可以看到我做错了什么,那就完美了,否则我会同时做课程并检查我的问题。 【参考方案1】:

将以下内容添加到您的配置方法中

.cors().and()

【讨论】:

我做到了,他正在寻找 'org.springframework.web.filter.CorsFilter' 而我的 CorsFilter 在 'org.cedric.filters.CorsFilter' 中。所以,错误看起来像这样:Error Creating bean with name 'springSecurityFilterChain' 阅读docs.spring.io/spring-security/site/docs/current/reference/html/… 我在我的问题中添加了这段代码,因为在评论中它很难读。还是同样的问题,我误会了什么? 我删除了我在 WebConfig 类中写的内容,并删除了我的自定义 CorsFilter,然后在我的 configure 方法中添加 .cors 并像我的问题一样编写了 corsConfigurationSource 方法。 java 端运行,但我仍然得到允许访问错误。我忘了抹掉什么?我阅读了您给我的另一个答案,但仍然无法正常工作。 谢谢你,为我工作!无需单独配置 cors。

以上是关于带有 Spring Boot 和 Spring Security 的 Angular2的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Jersey 和监控 URL

带有 spring-boot 和 spring-security 的 JWT

带有undertow servlet容器的spring-boot应用程序中的“没有共同的密码套件”错误

带有 FeignClient 的 Spring Boot RepositoryRestResource

带有 Jersey 和 Spring Security OAuth2 的 Spring Boot

带有 Spring-cloud-aws 和 cloudwatch 指标的 Spring Boot