Ok, so when I use my Rest Client (Insomnia). I am able to log into my Spring Server and successfully retrieves data afterwards.
But when I try to use my angularJS Client. 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.
You may notice X-AUTH-TOKEN in the code. 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.
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.
Below is my 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
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.
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. But I tried adding the exact same headers to the Rest Client and it still works.
Here is my angularjs call
$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.
The credential info, which is cookie/session id in this case, should be carried with your request for retrieving data in browser. The angular client can be configured like the following to do that.
$httpProvider.defaults.withCredentials = true;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.