java - 禁用CORS错误时Spring安全默认登录不起作用
问题描述
我在 spring boot 和 angualar9 上构建了一个应用程序。我得到了没有'Access-Control-Allow-Origin' header is present on the requested resource
错误。所以,我修复了这个错误,但是,现在当我停止 spring boot 应用程序并再次运行以测试任何 api 或任何其他页面时,我没有得到默认登录屏幕来输入由提供的用户名和密码弹簧安全。所以,这使我的弹簧安全不起作用。我认为当我禁用 CORS 策略时存在一些问题。
我的春季安全配置是:
Webconfig.java
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
网络安全配置.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
protected CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/books").permitAll()
.antMatchers("/api/v1/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.and().csrf().disable();
}
}
BasicAuthController.java
@RequestMapping("/api/v1")
@RestController
@CrossOrigin(origins ="http://localhost:4200")
public class BasicAuthController {
@GetMapping(path = "/basicauth")
public AuthenticationBean basicauth() {
System.out.println("hitted here");
return new AuthenticationBean("You are authenticated");
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.15.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>in.ashwin</groupId>
<artifactId>onlinebookstore</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>onlinebookstore</name>
<description>Angular 8 and spring boot fullstack</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
解决方案
您应该为登录的数据和路径添加登录页面的配置方法规范,使用.autenticated()
.
permitAll()
告诉春天你不在乎用户是否登录。如果您愿意,还可以添加自定义登录路径.loginPage("custom_url")
编辑 如果您使用角度,我建议使用过滤器作为流动我将使用 JWT 身份验证,但您可以使用其他方式。
JWt fliter:负责验证登录用户的身份验证。
@Component
public class JwtFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
private final UserService userService;
@Autowired
public JwtFilter( JwtUtil jwtUtil, UserService userService) {
this.jwtUtil = jwtUtil;
this.userService = userService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
/// user data should be some unique identifier. may be encrypted
String userData = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null) {
if (requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
userData= jwtTokenUtil.getDataFromToken(jwtToken);
} catch (Exception e) {
logger.error("JwtRequestFilter.doFilterInternal Unable to get JWT Token", e);
}
}
// Once we get the token validate it.
if (userData!= null) {
Optional<User> optionalUserObject = userService.findByData(userData);
if (optionalUser.isEmpty()){
throw new UsernameNotFoundException("User not found.");
}
User actualUser = optionalUserObject.get();
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
actualUser,null,actualUser.getRoles());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
configure
那么您应该使用该方法定义需要身份验证的 url
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// We don't need CSRF for this example
httpSecurity.csrf().disable()
// dont authenticate this particular request
.authorizeRequests().antMatchers("/login", "/register").permitAll().
// all other requests need to be authenticated
anyRequest().authenticated().and() exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and();
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
httpSecurity.cors();
}
像你已经完成的那样添加 cors 配置。
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint,
Serializable {
private static final long serialVersionUID = -7078141869840704968L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
希望我没有忘记任何东西,它会为你工作。
推荐阅读
- python - KMeans 聚类多维特征
- php - 通过 CSV 复制记录更新数据库
- android - 使用自定义布局在动作模式中包装标题文本
- typo3 - 在 Typo3 中为 Mask-Elements 设置后端标题
- elixir - 迁移数据库约束
- python - 在循环网络上使用预训练的句子嵌入
- symfony - 教义 find() 和 querybuilder() 在 PHPUnit 测试中返回不同的结果
- android-studio - Flutter build.gradle 麻烦
- jdbc - 无法使用 Java JDBC 从 AWS EMR 上的 Presto 连接/查询
- javascript - 已声明标识符 - 已声明标识符“userScore”