java - 现有端点的未经授权的错误 401,服务器日志中未引发错误
问题描述
我将用户名和密码字段添加到现有客户实体。我添加了一个自定义 JWT 过滤器和身份验证提供程序,其中 WebSecurityConfig 注释为 @Order(2)。但是当我发送带有用户名和密码有效负载的发布请求时,我收到未经授权的错误 401 响应但服务器日志中没有错误消息我已经适当地检查了 WebConfig 文件。我做错了什么?我整天都在做这件事,我似乎已经很沮丧了。
这是UserDetails类
public class MyCustomerDetails implements UserDetails{
/**
*
*/
private static final long serialVersionUID = -5087929420394311276L;
private Long id;
private String username;
private String password;
public MyCustomerDetails() {
}
public MyCustomerDetails(Long id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public static MyCustomerDetails build(Customer customer) {
return new MyCustomerDetails(customer.getId(),
customer.getUserName(), customer.getPassword());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return password;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return username;
}
............
这是控制器类
@CrossOrigin(origins = {"http://localhost:3000"})
@RestController
public class CustomerController {
@Autowired
CustomerAccountService customerRepo;
@Autowired
private CustomerJwtTokenUtil customerJwtTokenUtil;
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping(value="/validateCustomer")
public ResponseEntity <?> createAuthenticationToken( @RequestBody MyCustomerDetails
authenticationRequest) throws Exception
{
authenticate(authenticationRequest.getUsername(),
authenticationRequest.getPassword());
// Long userId = authenticationRequest.getId();
final MyCustomerDetails userDetails =
(MyCustomerDetails) customerRepo.loadUserByUsername(authenticationRequest.getUsername());
final String token =
customerJwtTokenUtil.generateToken(userDetails);
return new ResponseEntity<>(new JwtResponse(token), HttpStatus.OK) ;
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
这是WebSecurityconfig类
@Configuration
@Order(2)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomerSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomerJwtAuthenticationEntryPoint customerJwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService myCustomerDetailsService;
@Autowired
private CustomerJwtRequestFilter customerJwtRequestFilter;
@Bean
public CustomerAccountService myCustomerAccountService() {
return new CustomerAccountService();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/*
* @Bean public UserDetailsService myCustomerDetailsService() { return
* myCustomerDetailsService(); }
*/
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder,
UserDetailsService userDetailsService){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
return daoAuthenticationProvider;
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
protected void configure(AuthenticationManagerBuilder auth ) throws Exception {
auth.userDetailsService(myCustomerDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/***").permitAll()
// .antMatchers("/customer/**").hasAuthority("CUSTOMER")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(customerJwtAuthenticationEntryPoint)
.and()
.formLogin().permitAll()
// .loginPage("/login")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login")
.and()
.sessionManagement()
.maximumSessions(1)
.and()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(customerJwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
服务类
@Primary
public class CustomerAccountService implements UserDetailsService {
@Autowired
private CustomerAccountRepo custRepo;
@Qualifier("passwordEncoder")
@Autowired
private PasswordEncoder bCryptPasswordEncoder;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Customer customer = custRepo.findByUserName(username);
if(customer == null) {
throw new UsernameNotFoundException("Customer not found");
}
return MyCustomerDetails.build(customer);
}
这是基类
@Configuration
@EnableWebMvc
//@ComponentScan(basePackages = "com.bethsaida.org.security")
@EnableJpaRepositories
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class BethsaidaApplication {
public static void main(String[] args)
{SpringApplication.run(BethsaidaApplication.class, args);}
public class WebConfig implements WebMvcConfigurer
{
private static final long MAX_AGE_SECS = 3600;
@Override
public void addCorsMappings(CorsRegistry registry)
{ registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
.maxAge(MAX_AGE_SECS);}
}
}
解决方案
你可以用这个
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "PUT", "DELETE")
.allowedHeaders("header1", "header2")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
直接在你的CustomerSecurityConfiguration
班级里面。因为WebMvcConfigurer
是由实现的,WebMvcConfigurerAdapter
所以你可以在你的CustomerSecurityConfiguration
类中定义这个方法。
有关更多信息,您可以在此处查看
推荐阅读
- c++ - C++ 重载解析查询
- javascript - 在Javascript中将具有01值的数字输入到toString
- polymer-1.0 - 多路径对象数组变异
- javascript - Html画布在抚摸线条时闪烁
- vue.js - Nuxtjs 挂钩系统
- facebook - Facebook Graph 获取用户被邀请参加的所有事件
- regex - 在 Django URL 中调整正则表达式以匹配文件路径
- elasticsearch - 如何按 Docker 实例对 Elastic Stack 警报进行分组?
- php - CakePHP 3 - 将实体字段 FLOAT 保存为 INTEGER
- laravel - Laravel 5.6 调用未定义的方法 Illuminate\\Auth\\GenericUser::withAccessToken()