[英]Spring Boot Authorizes User In Rest Client, But Not In Browser (Rest Authorization)
Ok, so when I use my Rest Client (Insomnia). 好的,所以当我使用我的Rest Client(失眠)时。 I am able to log into my Spring Server and successfully retrieves data afterwards. 我能够登录到我的Spring Server,然后成功检索数据。
But when I try to use my angularJS Client. 但是当我尝试使用我的angularJS客户端时。 I can successfully log in but then when I try to retrieve data, it sends back a 401 error as if it forgot I ever logged in. I am very confused. 我可以成功登录,但是当我尝试检索数据时,它会发送回401错误,好像它忘记了我登录一样。我非常困惑。
You may notice X-AUTH-TOKEN in the code. 您可能会在代码中注意到X-AUTH-TOKEN。 As of right now, I do not have it setup where it is checking X-AUTH-TOKEN so disregard this and please note that it WORKS in my REST CLIENT but not in the Browser Client. 截至目前,我还没有在检查X-AUTH-TOKEN的位置安装它,因此请忽略此设置,请注意,它在我的REST CLIENT中有效,但在Browser Client中却无效。
I even tried to add the same amount of request header information in my REST CLIENT as my browser client, it still retrieves data for it. 我什至尝试在REST CLIENT中添加与浏览器客户端相同数量的请求标头信息,但它仍会为其检索数据。
Below is my WebSecurityConfig 以下是我的WebSecurityConfig
package app.config;
import app.repo.User.CustomUserDetailsService;
import app.security.RESTAuthenticationEntryPoint;
import app.security.RESTAuthenticationFailureHandler;
import app.security.RESTAuthenticationSuccessHandler;
import app.security.TokenAuthenticationService;
import app.security.filters.StatelessAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.sql.DataSource;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static PasswordEncoder encoder;
@Autowired
private TokenAuthenticationService tokenAuthenticationService;
private CustomUserDetailsService userService;
@Autowired
private UserDetailsService customUserDetailsService;
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
public void configureAuth(AuthenticationManagerBuilder auth,DataSource dataSource) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").authenticated();
http.csrf().disable();
http.httpBasic();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().defaultSuccessUrl("/").successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
// http.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService),
// UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
@Bean
@Override
public CustomUserDetailsService userDetailsService() {
return userService;
}
@Bean
public TokenAuthenticationService tokenAuthenticationService() {
this.userService = new CustomUserDetailsService();
tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets", customUserDetailsService);
return tokenAuthenticationService;
}
}
I also have a CorsFilter 我也有一个CorsFilter
package app.config;
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 CorsFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(CorsFilter.class);
public CorsFilter() {
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-Expose-Headers", "X-Auth-Token");
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() {
}
}
Why is it that Spring accepts my Spring Requests after logging in, but not my Client Request after logging in. 为什么登录后Spring接受我的Spring Request,但登录后却不接受Client Request。
I check If the user is authenticated via persistent database 我检查用户是否通过持久数据库进行了身份验证
package app.repo.User;
import app.cache.UserService;
import app.security.UserAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@Qualifier("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepo userRepository;
@Autowired
private UserService userService;
private final AccountStatusUserDetailsChecker detailsChecker = new AccountStatusUserDetailsChecker();
private final HashMap<String, User> userMap = new HashMap<String, User>();
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username)
throws UsernameNotFoundException {
app.repo.User.User user = userRepository.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("Bad Credentials");
}
userService.setUserInfo(user);
List<GrantedAuthority> authorities = buildUserAuthority(user.getRoles());
UserDetails userDetails = buildUserForAuthentication(user, authorities);
// detailsChecker.check(userDetails);
return userDetails;
}
private UserDetails buildUserForAuthentication(app.repo.User.User user,
List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(), authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRoleName()));
}
return new ArrayList<GrantedAuthority>(setAuths);
}
public void addUser(User user) {
userMap.put(user.getUsername(), user);
}
}
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:0
Host:localhost:8080
Origin:http://localhost:8100
Referer:http://localhost:8100/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Accept, X-Requested-With, remember-me
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:8100
Access-Control-Expose-Headers:X-Auth-Token
Access-Control-Max-Age:3600
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Length:88
Date:Thu, 19 Nov 2015 16:22:39 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=966F22A08A6D30E73FDC0DF40749C5C2; Path=/; HttpOnly
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:0
Host:localhost:8080
Origin:http://localhost:8100
Referer:http://localhost:8100/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Accept, X-Requested-With, remember-me
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:8100
Access-Control-Expose-Headers:X-Auth-Token
Access-Control-Max-Age:3600
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Type:application/json;charset=UTF-8
Date:Thu, 19 Nov 2015 16:25:03 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
For my Rest Client. 对于我的其他客户。 The Response Headers are the Same. 响应头是相同的。 For The Request headers for Rest Client, It doesnt have any to show. 对于Rest Client的Request标头,没有任何显示。 But I tried adding the exact same headers to the Rest Client and it still works. 但是我尝试将完全相同的标头添加到Rest Client,它仍然可以工作。
Here is my angularjs call 这是我的angularjs电话
$http({
method: 'POST',
url: loginUrl
}).then(function successCallback(response) {
var resp = response;
$http({
method: 'POST',
url: $scope.siteUrl+'/get-all-games'
}).then(function successCallback(response) {
var resp = response;
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
var resp = response;
// called asynchronously if an error occurs
// or server returns response with an error status.
});
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
var resp = response;
// called asynchronously if an error occurs
// or server returns response with an error status.
});
I setup my $http call to do a call to retrieve data immediately after success of login... It still returns a 401 error even though I successfully logged in. 我设置了$ http调用,以成功登录后立即进行检索数据的调用...即使我成功登录,它仍然返回401错误。
The credential info, which is cookie/session id in this case, should be carried with your request for retrieving data in browser. 凭据信息(在这种情况下为cookie /会话ID)应与您在浏览器中检索数据的请求一起携带。 The angular client can be configured like the following to do that. 可以像下面这样配置角度客户端。
$httpProvider.defaults.withCredentials = true;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.