简体   繁体   English

Spring Boot在Rest Client中授权用户,但未在浏览器中授权用户(Rest授权)

[英]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);
    }
}

Here is my Request Headers for Browser LOGIN 这是我的浏览器登录请求头

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

Here are response headers for browser LOGIN 这是浏览器登录的响应头

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

Here are Request Headers For Retrieving Data in browser 这是在浏览器中检索数据的请求标头

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

response headers for retrieving data Data in Browser 用于在浏览器中检索数据的响应头

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.

相关问题 Spring Boot REST API 应用级授权 - Spring Boot REST API application level authorization 将权限和用户主体从 rest 客户端传递到服务器 spring 启动 - Passing authorities and user principal from rest client to server spring boot Spring 引导 REST API - 通过客户端类型(浏览器/非浏览器)启用/禁用 CSRF 保护? - Spring Boot REST API - enable / disable CSRF protection by client type (browser / non-browser)? Spring 启动 CLI 客户端使用 Rest Api - Spring boot CLI client consuming Rest Api Spring 引导中 Rest 客户端 Junit 的 InvalidUseOfMatchersException - InvalidUseOfMatchersException for Rest Client Junit in Spring Boot 使用@RestClientTest对rest客户端进行Spring启动测试 - Spring boot testing of a rest client using @RestClientTest 创建一个Java REST客户端以调用Spring Boot REST API - Create a java REST client to call a spring boot REST API Spring 启动 - rest 客户端来自 rest Z594C103F2C6E04C3D8AB059F0310E 接口C - Spring boot - rest client from rest controller interface Spring Security REST授权 - Spring Security REST authorization 使用Spring Boot的Rest API不会通过angular向客户端返回数据:产生来自浏览器的404响应 - Rest api using Spring boot not returning data to client via angular: yields 404 response from browser
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM