当前位置: 首页 > 知识库问答 >
问题:

AngularJS SpringSecurity CORS问题

鲍建业
2023-03-14

我正在设置Angular Spring Security模块来登录和注册用户。当我注册一个用户时,一切都正常。注册后的最后一步是自动登录,但我遇到了以下错误:

XMLHttpRequest无法加载超文本传输协议//localhost:8080/com-tesis/login.请求的资源上不存在“访问控制允许起源”标头。因此不允许访问起源“超文本传输协议//localhost:9000”。响应的HTTP状态代码为401。

angularJs端服务:

.factory("sessionAccountService", function($http){
        var session = {};
        session.login = function(data){
            return $http.post("http://localhost:8080/com-tesis/login",
                              "username="+data.name+"&password="+data.password,
                              {headers: {"Access-Control-Allow-Headers":"Content-Type"}}
            ).then(function(data){
                alert("loggin correcto");
                localStorage.setItem("session",{});
            }, function(data){
                alert("error login in");
            });

        };
        session.logout = function(){
            localStorage.removeItem("session");
        };
        session.isLoggedIn = function(){
            return localStorage.getItem("session") !== null;
        }
        return session;
    })
  .factory("accountService", function($resource){
        var service = {};
        service.register = function(account, success, failure){
            var Account = $resource("http://localhost:8080/com-tesis/rest/accounts");
            Account.save({},account,success,failure);
        };
        service.userExists = function(account, success, failure){
            var Account = $resource("http://localhost:8080/com-tesis/rest/accounts");
            var data = Account.get({name:account.name}, function(){
                var accounts = data.accounts;
                if (accounts.length !== 0){
                    success(accounts[0]);
                } else {
                    failure();
                }
            }, 
            failure);
        }
        return service;
    });

这是在后端实现的CORS过滤器:

package tesis.core.security;

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, HEAD");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

}

这是web.xml过滤器

<filter>
        <filter-name>simpleCORSFilter</filter-name>
        <filter-class>
            tesis.core.security.SimpleCORSFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>simpleCORSFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

我很困惑,这是Chrome网络请求:req/res

我不知道我做错了什么。谢谢

编辑:当我从同一个网址发送请求时,超文本传输协议//localhost:8080/完美运行。从超文本传输协议//localhost:9000Spring总是返回SC_UNAUTHORIZED

这是SecurityConfig

package tesis.core.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private AuthFailure authFailure;

    @Autowired
    private AuthSuccess authSuccess;

    @Autowired
    private EntryPointUnauthorizedHandler unauthorizedHandler;

    @Autowired 
    private UserDetailServiceImpl userDetailService;

    @Autowired
    public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception{
        builder.userDetailsService(userDetailService);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .and()
            .formLogin()
                .successHandler(authSuccess)
                .failureHandler(authFailure)
            .and()
            .authorizeRequests()
                .antMatchers("/**")
                .permitAll();
    }
}

Auth成功和AuthFailure类

package tesis.core.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

@Component
public class AuthSuccess extends SimpleUrlAuthenticationSuccessHandler{

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {

        response.setStatus(HttpServletResponse.SC_OK);
    }

}

package tesis.core.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

@Component
public class AuthFailure extends SimpleUrlAuthenticationFailureHandler{

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {

        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
}

共有1个答案

庞书
2023-03-14

我终于找到了解决办法。首先,为了解决401错误,我重写了这里的请求:401解决方案

之后,出现了一个新的错误:

请求的资源上不存在“Access-Control-Allow-Origin”标头,因此不允许访问Origin。

然后,在阅读Spring文档时,我意识到我必须明确告诉Spring要使用哪个标题。这里的线索是:Spring文档:header static

所以,这是修复的SecurityConfig文件:

package tesis.core.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.header.writers.StaticHeadersWriter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private AuthFailure authFailure;

    @Autowired
    private AuthSuccess authSuccess;

    @Autowired
    private EntryPointUnauthorizedHandler unauthorizedHandler;

    @Autowired 
    private UserDetailServiceImpl userDetailService;

    @Autowired
    public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception{
        builder.userDetailsService(userDetailService);
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new SimpleUrlAuthenticationFailureHandler();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .headers().addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin","*"))
            .and()
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .and()
            .formLogin()
                .successHandler(authSuccess)
                .failureHandler(authFailure)
            .and()
            .authorizeRequests()
                .antMatchers("/**")
                .permitAll();
    }
}

谢谢大家。

 类似资料:
  • 问题内容: 包括: all Spring libs, Apache Tomcat 7.0 library 在构建路径中 但它仍然给出错误: 在“ org.sprintframework.web-3.1.0.M1.jar”中,我可以看到“ org.springframework.web.context.ContextLoaderListener”。 Google上的某个人说应该包含spring.ja

  • 问题内容: 我使用非常简单的代码返回XML 但是,出现以下错误 请帮忙。谢谢 问题答案: 运行时出现NoSuchMethodError表示你使用的库版本与生成代码所针对的版本不同。 在你的情况下,Spring是元凶。在运行时检查类路径上的内容,并确保以下各项: 版本与编译时间罐相同 如果存在多个版本,请删除不需要的版本

  • 问题内容: 我不明白注释和之间的实际区别是什么? 扩展名还是它们具有完全不同的含义?什么时候应该使用它们?在服务层中使用Spring ,在DAO 中使用javax? 谢谢回答。 问题答案: 几年前,Spring定义了自己的Transactional注释以使Spring bean方法具有事务性。 Java EE 7终于做了同样的事情,现在除了EJB方法外,还允许CDI bean方法是事务性的。因此,

  • 我在CentOS虚拟机中安装了RabbitMQ,该虚拟机的网络适配器被定义为Bridge。我正在尝试配置RabbitMQ管理,以便通过机器的IP地址访问WebApp。配置如下:

  • 这个FAQ的最新版本总是可以从Apache主站点得到,位于<http://httpd.apache.org/docs/2.2/faq/> 如果你的问题在这里没有找到答案,你也可以看看Apache 1.3 FAQ ,看你的问题是否在那里有了答案。 主题 背景 关于 Apache HTTP Server 的背景知识。 支持 我遇到问题该怎么办? 错误信息 这些错误信息是什么意思? 背景 什么是Apac

  • 发布问题 更新问题 设置问题悬赏 获取问题列表 获取一个问题详情 删除一个问题 获取用户发布的问题列表 发布问题 POST /questions 输入 字段 类型 描述 subject 字符串 必须,问题主题或者说标题,不能超过 255 字节 ,必须以 ? 结尾。(不区分全角或者半角) topics 数组 必须,绑定的话题,数组子节点必须符合 { "id": 1 } 的格式。 body 字符串

  • 问题内容: 我简直不敢相信我网站上正在发生的事情。当我添加此行时: 一切正常。如果我不这样做,CSS就会“混乱”,一切都会变得不同,布局也会变得“丑陋”。 这条线如何解决所有问题? 问题答案: 您正在将HTML与XHTML混合使用。 通常,声明用于区分HTMLish语言的版本(在这种情况下为HTML或XHTML)。 不同的标记语言将表现不同。我最喜欢的例子是。在浏览器中查看以下内容: XHTML

  • 我试图在fabric rocket chat上联系,但没有得到太多帮助,因此在SO上发布了它。我有以下疑问: 我们是否可以在链码内访问块高度(我知道这在客户端是可行的,但在链码内是否可能) 可以从链码中的正在进行的事务调用新事务吗? 想知道hyperledger Fabric中存储的数据的历史记录在哪里 我们可以根据链码中的transactionid进行查询吗? 在fabric链码中编写调度程序是