spring引导api给出403禁止的错误

igetnqfo  于 2021-09-30  发布在  Java
关注(0)|答案(2)|浏览(307)

我有一个spring启动应用程序,其中包含mongo数据库和Spring Security 作为依赖项。它有两个服务,第一个用于身份验证,第二个用于应用程序资源(实体、服务控制器)。这是身份验证服务中的我的配置类:

@Configuration
@EnableWebSecurity
public class AuthServerSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
@Bean
protected UserDetailsService userDetailsService() {
    return new MongoUserDetailsService();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
    .authorizeRequests().anyRequest().authenticated();
    System.out.println("auth");
}

@Override
public void configure(WebSecurity web) throws Exception {
    super.configure(web);
}

@Bean(name="authenticationManager")
@Lazy
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}
}

这是rest控制器:

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping(value = "/api/users")
public class UserController {

@Autowired
UserServiceImpl userServiceImpl;

//Getting all users
@GetMapping(value = "")
public List<UserDTO> getAllUsers() {
    return userServiceImpl.getAllUsers();

}

//Getting a user by ID
@GetMapping(value = "/profil/{userId}")
public UserDTO getUserById(@PathVariable String userId) {
    return userServiceImpl.getUserById(userId);
}

//Getting a user by Username
@GetMapping(value = "/profil/username/{username}")
public UserDTO getUserByUsernameOrEmail(String username) {
    return userServiceImpl.getUserByUsernameOrEmail(username);
}

//Logout user and delete token
@PostMapping("/logout")
public void logout(HttpServletRequest request) {
     userServiceImpl.logout(request);

}

我将配置方法更改为:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    .authorizeRequests() // authorize
    .anyRequest().authenticated() // all requests are authenticated
    .and()
    .httpBasic();

    http.cors();

}

现在我在访问受保护的资源时得到401未经授权。问题是,即使我在请求头中发送了正确的承载令牌,我仍然得到401未经授权的“访问此资源需要完全身份验证”
更新:我将我的项目架构从microservices更改为一个简单的springboot项目。这是类“authserversecurityconfig”的新代码

@Configuration
public class AuthServerSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
@Bean
protected UserDetailsService userDetailsService() {
    return new MongoUserDetailsService();
}

@Autowired
BCryptPasswordEncoder passwordEncoder;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //auth.userDetailsService(userDetailsService());
    auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    .anonymous().disable()
    .authorizeRequests()
    .antMatchers("/oauth/token").permitAll().and()
    .httpBasic();

    http.cors();
}

@Override
public void configure(WebSecurity web) throws Exception {
    super.configure(web);
}

@Bean(name="authenticationManager")
@Lazy
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}
}

下面是“resourceserverconfig”代码:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Autowired private ResourceServerTokenServices tokenServices;

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("foo").tokenServices(tokenServices);
}

@Override
public void configure(HttpSecurity http) throws Exception {

        http
        .authorizeRequests() // authorize
        .antMatchers("/oauth/**").permitAll();

        http
        .authorizeRequests().antMatchers("/api/**").authenticated();

        http
        .headers().addHeaderWriter(new HeaderWriter() {
        @Override
        public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
            response.addHeader("Access-Control-Allow-Origin", "*");
            if (request.getMethod().equals("OPTIONS")) {
                response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
                response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            }
        }
    });
}
}

当我尝试访问受保护的资源时,我得到“错误”:“未经授权”,“错误描述”:“访问此资源需要完全身份验证”,这是正常行为。问题是现在我无法登录以获取用户访问令牌。
访问此端点时,我得到“401未经授权”http://localhost:8080/oauth/token?grant_type=password&username=user&password=user".
这些是默认的init用户凭据,并且该用户存在于my mongodatabase中,密码以“$2a”开头,格式正确,字符为“60”。
尝试登录时,我在控制台中输入“编码密码看起来不像bcrypt身份验证失败:密码与存储值不匹配”。

lpwwtiir

lpwwtiir1#

在里面 ResourceServerConfig 类文件,在 configure 方法更改为下面的代码。

http
    .csrf().disable()
    .anonymous().disable()
    .authorizeRequests()
    .antMatchers("/oauth/token").permitAll().and()
    .httpBasic();

让我知道它是否有效。

rekjcdws

rekjcdws2#

下面是一个使用jwt令牌检查的配置Spring Security 示例:您可以将数据源从h2更改为mongodb,并找到my repo中使用的过滤器和提供程序:

https://github.com/e2rabi/sbs-user-management/tree/main/sbs-user-management

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@FieldDefaults(level = PRIVATE, makeFinal = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
             // Put your public API here 
            new AntPathRequestMatcher("/public/**"),
            new AntPathRequestMatcher("/h2-console/**"),

    );
    private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);

    TokenAuthenticationProvider provider;

    SecurityConfig(final TokenAuthenticationProvider provider) {
        super();
        this.provider = requireNonNull(provider);
    }

   @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(provider);
    }
    @Override
    public void configure(final WebSecurity web) {
        web.ignoring().requestMatchers(PUBLIC_URLS);
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http
                .sessionManagement()
                .sessionCreationPolicy(STATELESS)
                .and()
                .exceptionHandling()
                // this entry point handles when you request a protected page and you are not yet
                // authenticated
                .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
                .and()
                .authenticationProvider(provider)
                .addFilterBefore(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .authenticated()
                .and()
                .csrf().disable()
                .cors().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();

                // h2 console config
                http.headers().frameOptions().sameOrigin();
                // disable page caching
                http.headers().cacheControl();
    }

    @Bean
    TokenAuthenticationFilter restAuthenticationFilter() throws Exception {
        final TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(successHandler());
        return filter;
    }

    @Bean
    SimpleUrlAuthenticationSuccessHandler successHandler() {
        final SimpleUrlAuthenticationSuccessHandler successHandler = new SimpleUrlAuthenticationSuccessHandler();
        successHandler.setRedirectStrategy(new NoRedirectStrategy());
        return successHandler;
    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    FilterRegistrationBean disableAutoRegistration(final TokenAuthenticationFilter filter) {
        final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
        registration.setEnabled(false);
        return registration;
    }

    @Bean
    AuthenticationEntryPoint forbiddenEntryPoint() {
        return new HttpStatusEntryPoint(FORBIDDEN);
    }
}

相关问题