弹簧引导CORS和angularjs不工作 [英] CORS with spring-boot and angularjs not working
问题描述
我想呼吁从另一个(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
私人的UserDetailsService的UserDetailsService; @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()
。和()
。记住我()
.userDetailsService(UserDetailsService中)
.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屋!