弹簧引导CORS和angularjs不工作 [英] CORS with spring-boot and angularjs not working

查看:165
本文介绍了弹簧引导CORS和angularjs不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想呼吁从另一个(angularjs)一个应用程序(春季启动应用程序)REST端点。这些应用程序在以下主机和端口上运行。


  • REST应用,利用春天开机,的http://本地主机:8080

  • HTML应用程序,使用angularjs,的http://本地主机:50029

我也使用春季安全通过弹簧启动应用程序。从HTML应用程序,我可以验证到REST的应用程序,但是,此后,我仍然无法访问任何REST端点。例如,我有一个angularjs服务定义如下:

  adminServices.factory('AdminService',['$资源,$ HTTP','的conf',函数($资源,$ HTTP,CONF){
    变种S = {};
    s.isAdminLoggedIn =功能(数据){
        返回$ HTTP({
            方法:GET,
            网址:的http://本地主机:8080 / API /管理/ isloggedin',
            withCredentials:真实,
            标题:{
                X-要求,以:XMLHtt prequest
            }
        });
    };
    s.login =功能(用户名,密码){
        变种U ='用户名='+ EN codeURI(用户名);
        变种p值='密码='+ EN codeURI(密码);
        变种R ='remember_me = 1';
        VAR数据= U +'和;' + P +'和;' + R;        返回$ HTTP({
            方法:POST,
            网址:的http://本地主机:8080 /登录',
            数据:数据,
            标题:{内容类型:应用程序/ x-WWW的形式urlen codeD'}
        });
    };
    返回S;
}]);

该angularjs控制器看起来像下面这样。

  adminControllers.controller('的LoginController',['$范围,$ HTTP,AdminService',函数($范围,$ HTTP,AdminService){
    $ scope.username ='';
    $ scope.password ='​​';    $ scope.signIn =功能(){
        AdminService.login($ scope.username,$ scope.password)
            .success(功能(D,S){
                如果(D ['成功']){
                    的console.log('OK认证,调用另一个REST端点');
                    AdminService.isAdminLoggedIn()
                        .success(功能(D,S){
                            的console.log('我可以在登录后访问受保护的REST端点');
                        })
                        .error(功能(D,S){
                            的console.log('呵呵,错误检查,以查看是否管理员已经登录');
                            $ scope.reset();
                        });
                }其他{
                    的console.log(坏凭据?');
                }
            })
            .error(功能(D,S){
                的console.log('呵呵,错误发生了!');
            });
    };
}]);

在调用的http://本地主机:8080 / API /管理/ isloggedin ,我收到了 401未授权

在REST应用方面,我有一个CORS筛选器看起来像下面这样。

  @Component
@Order(Ordered.HIGHEST_ preCEDENCE)
公共类CORSFilter实现过滤器{    @覆盖
    公共无效的destroy(){}    @覆盖
    公共无效的doFilter(ServletRequest中REQ,ServletResponse的资源,FilterChain链)
            抛出IOException异常,ServletException异常{
        HttpServletResponse的响应=(HttpServletResponse的)资源;
        HttpServletRequest的请求=(HttpServletRequest的)REQ;        response.setHeader(访问控制允许原产地,HTTP://本地主机:50029);
        response.setHeader(访问控制允许的方法,POST,PUT,GET,OPTIONS,DELETE);
        response.setHeader(访问控制-max-age的,3600);
        response.setHeader(访问控制允许报头,X-请求 - 由于X-验证令牌);
        response.setHeader(访问控制允许的凭据,真);        如果(!OPTIONS.equalsIgnoreCase(request.getMethod())){
            chain.doFilter(REQ,RES);
        }
    }    @覆盖
    公共无效的init(一个FilterConfig配置)抛出了ServletException {}
}

我的春季安全配置看起来像下面这样。

  @Configuration
@EnableWebSecurity
公共类WebSecurityConfig扩展WebSecurityConfigurerAdapter {    @Autowired
    私人RestAuthenticationEntryPoint restAuthenticationEntryPoint;    @Autowired
    私人JsonAuthSuccessHandler jsonAuthSuccessHandler;    @Autowired
    私人JsonAuthFailureHandler jsonAuthFailureHandler;    @Autowired
    私人JsonLogoutSuccessHandler jsonLogoutSuccessHandler;    @Autowired
    私人的AuthenticationProvider的AuthenticationProvider;    @Autowired
    私人的UserDetailsS​​ervice的UserDetailsS​​ervice;    @Autowired
    私人PersistentTokenRepository persistentTokenRepository;    @Value($ {rememberme.key})
    私人字符串rememberMeKey;    @覆盖
    保护无效配置(HttpSecurity HTTP)抛出异常{
        HTTP
            .csrf()。禁止()
            。异常处理()
            .authenticationEntryPoint(restAuthenticationEntryPoint)
                。和()
            .authorizeRequests()
                .antMatchers(/ API /管理/ **)。hasRole(ADMIN)
                .antMatchers(/,/管理员,/ CSS / **,/ JS / **,/字体/ **,/ API / **)。permitAll()
                .anyRequest()认证()
                。和()
            .formLogin()
                .successHandler(jsonAuthSuccessHandler)
                .failureHandler(jsonAuthFailureHandler)
                .permitAll()
                。和()
            。登出()
                .deleteCookies(记住我,JSESSIONID)
                .logoutSuccessHandler(jsonLogoutSuccessHandler)
                .permitAll()
                。和()
            。记住我()
                .userDetailsS​​ervice(UserDetailsS​​ervice中)
                .tokenRepository(persistentTokenRepository)
                .rememberMeCookieName(REMEMBER_ME)
                .rememberMeParameter(remember_me)
                .tokenValiditySeconds(1209600)
                .useSecureCookie(假)
                .KEY(rememberMeKey);
    }    @Autowired
    公共无效configureGlobal(AuthenticationManagerBuilder AUTH)抛出异常{
        AUTH
            .authenticationProvider(AuthenticationProvider的);
    }
}

所有的处理程序正在做的是写出像的JSON响应{成功:真正} 的基础上,如果用户登录,无法进行身份验证,或注销。在 RestAuthenticationEntryPoint 看起来像下面这样。

  @Component
公共类RestAuthenticationEntryPoint实现的AuthenticationEntryPoint {    @覆盖
    公共无效动工(HttpServletRequest的REQ,HttpServletResponse的RESP,恩的AuthenticationException)
            抛出IOException异常,ServletException异常{
        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED,未经授权);
    }}

这是什么,我丢失或做错了任何想法?


解决方案

 进口java.io.IOException异常;
进口javax.servlet.Filter的;
进口javax.servlet.FilterChain;
进口javax.servlet.FilterConfig;
进口javax.servlet.ServletException;
进口javax.servlet.ServletRequest;
进口javax.servlet.ServletResponse;
进口javax.servlet.http.HttpServletRequest;
进口javax.servlet.http.HttpServletResponse;
进口org.slf4j.Logger;
进口org.slf4j.LoggerFactory;
进口org.springframework.stereotype.Component;@零件
公共类SimpleCORSFilter实现过滤器{私人最终记录器记录= LoggerFactory.getLogger(SimpleCORSFilter.class);公共SimpleCORSFilter(){
    log.info(SimpleCORSFilter INIT);
}@覆盖
公共无效的doFilter(ServletRequest中REQ,ServletResponse的资源,FilterChain链)抛出IOException异常,ServletException异常{    HttpServletRequest的请求=(HttpServletRequest的)REQ;
    HttpServletResponse的响应=(HttpServletResponse的)资源;    response.setHeader(访问控制允许来源,request.getHeader(原点));
    response.setHeader(访问控制允许的凭据,真);
    response.setHeader(访问控制允许的方法,POST,GET,OPTIONS,DELETE);
    response.setHeader(访问控制-max-age的,3600);
    response.setHeader(访问控制允许报头,内容类型,接受,X-要求-着,记得我);    chain.doFilter(REQ,RES);
}@覆盖
公共无效的init(一个FilterConfig一个FilterConfig){
}@覆盖
公共无效的destroy(){
}}

没有需要额外的定义此过滤器只添加这个类。春天会扫描并添加它。 SimpleCORSFilter。
这里是例子:春季启用-CORS

I am trying to call REST endpoints on one application (spring-boot application) from another (angularjs). The applications are running on the following hosts and ports.

  • REST application, using spring boot, http://localhost:8080
  • HTML application, using angularjs, http://localhost:50029

I am also using spring-security with the spring-boot application. From the HTML application, I can authenticate to the REST application, but, thereafter, I still cannot access any REST endpoint. For example, I have an angularjs service defined as follows.

adminServices.factory('AdminService', ['$resource', '$http', 'conf', function($resource, $http, conf) {
    var s = {};
    s.isAdminLoggedIn = function(data) {
        return $http({
            method: 'GET',
            url: 'http://localhost:8080/api/admin/isloggedin',
            withCredentials: true,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        });
    };
    s.login = function(username, password) {
        var u = 'username=' + encodeURI(username);
        var p = 'password=' + encodeURI(password);
        var r = 'remember_me=1';
        var data = u + '&' + p + '&' + r;

        return $http({
            method: 'POST',
            url: 'http://localhost:8080/login',
            data: data,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        });
    };
    return s;
}]);

The angularjs controller looks like the following.

adminControllers.controller('LoginController', ['$scope', '$http', 'AdminService', function($scope, $http, AdminService) {
    $scope.username = '';
    $scope.password = '';

    $scope.signIn = function() {
        AdminService.login($scope.username, $scope.password)
            .success(function(d,s) {
                if(d['success']) {
                    console.log('ok authenticated, call another REST endpoint');
                    AdminService.isAdminLoggedIn()
                        .success(function(d,s) {
                            console.log('i can access a protected REST endpoint after logging in');
                        })
                        .error(function(d, s) { 
                            console.log('huh, error checking to see if admin is logged in');
                            $scope.reset();
                        });
                } else {
                    console.log('bad credentials?');
                }
            })
            .error(function(d, s) {
                console.log('huh, error happened!');
            });
    };
}]);

On the call to http://localhost:8080/api/admin/isloggedin, I get a 401 Unauthorized.

On the REST application side, I have a CORS filter that looks like the following.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {

    @Override
    public void destroy() { }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:50029");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException { }
}

My spring security configuration looks like the following.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    private JsonAuthSuccessHandler jsonAuthSuccessHandler;

    @Autowired
    private JsonAuthFailureHandler jsonAuthFailureHandler;

    @Autowired
    private JsonLogoutSuccessHandler jsonLogoutSuccessHandler;

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Value("${rememberme.key}")
    private String rememberMeKey;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthenticationEntryPoint)
                .and()
            .authorizeRequests()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/", "/admin", "/css/**", "/js/**", "/fonts/**", "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .successHandler(jsonAuthSuccessHandler)
                .failureHandler(jsonAuthFailureHandler)
                .permitAll()
                .and()
            .logout()
                .deleteCookies("remember-me", "JSESSIONID")
                .logoutSuccessHandler(jsonLogoutSuccessHandler)
                .permitAll()
                .and()
            .rememberMe()
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository)
                .rememberMeCookieName("REMEMBER_ME")
                .rememberMeParameter("remember_me")
                .tokenValiditySeconds(1209600)
                .useSecureCookie(false)
                .key(rememberMeKey);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(authenticationProvider);
    }
}

All the handlers are doing is writing out a JSON response like {success: true} based on if the user logged in, failed to authenticate, or logged out. The RestAuthenticationEntryPoint looks like the following.

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException ex)
            throws IOException, ServletException {
        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

}

Any ideas on what I am missing or doing wrong?

解决方案

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

No need extra define this filter just add this class. Spring will be scan and add it for you. SimpleCORSFilter. Here is the example: spring-enable-cors

这篇关于弹簧引导CORS和angularjs不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆