简体   繁体   English

禁用 CORS 错误时,Spring 安全默认登录不起作用

[英]Spring security default login not working when disabling CORS error

I have an application building on spring boot and angualar9.我在 spring 启动和 angualar9 上构建了一个应用程序。 I got the No 'Access-Control-Allow-Origin' header is present on the requested resource error.So,I fixed this error but,now when I stop the spring boot application and again run to test any api or any other pages then,I don't get default login screen to enter username and password provided by spring security.So,this made my spring security not working.I think there is some problem when i disabled CORS policy.我得到了 No 'Access-Control-Allow-Origin' header is present on the requested resource error. 所以,我修复了这个错误,但是,现在当我停止 spring 启动应用程序并再次运行以测试任何 Z8A5DA 或 70005 页面77 ,我没有得到默认登录屏幕来输入 spring 安全提供的用户名和密码。所以,这使我的 spring 安全不起作用。我认为当我禁用 Z5A8FEFF0B4BDE3EEC9244B76023 策略时存在一些问题。

My spring secutiry config is:我的 spring 安全配置是:

Webconfig.java Webconfig.java

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    
       @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
        }

}

WebSecutiryConfig.java Web安全配置.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 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 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>

You should add to your configure method specification of login page for the logged in data and paths with .autenticated() .您应该使用.autenticated()为登录的数据和路径添加登录页面的配置方法规范。 permitAll() is telling spring you dont care if the user is logged in or not. permitAll()告诉 spring 你不在乎用户是否登录。 You can also add a custom login path if you would like with .loginPage("custom_url")如果您愿意,还可以使用.loginPage("custom_url")添加自定义登录路径

Edit if you are using angular i would suggest using a filter as flowing i will use JWT authentication but you can use every other way.编辑如果您使用的是 angular 我建议使用过滤器作为流动我将使用 JWT 身份验证,但您可以使用其他所有方式。

JWt fliter: responsible for validating logged in users authentication. JWt 过滤器:负责验证登录用户的身份验证。

@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);
}
}

then you should define the urls that requires authentication with the configure method那么您应该使用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();
}

add cors configuration as you already done.按照您已经完成的方式添加 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");
}
}

hope i didn't forgot any Thing and it will work for you.希望我没有忘记任何东西,它会为你工作。

Replace @CrossOrigin(origins ="http://localhost:4200") to @CrossOrigin("*") Restart service and test将@CrossOrigin(origins ="http://localhost:4200") 替换为@CrossOrigin("*") 重启服务并测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM