Sping Boot ,Spring Security,React -自定义过滤器身份验证不起作用

btqmn9zl  于 2023-04-21  发布在  Spring
关注(0)|答案(1)|浏览(132)

在自定义过滤器中,请求中的用户名和密码显示为空。通过浏览器:http://username:password@localhost:8090/login我假设这将调用Spring Security的默认登录。在自定义过滤器中,请求中的用户名和密码显示为null,即使我给予了正确的用户名和密码。因此凭据失败。因此返回403。自定义过滤器是否未注册或未获得请求。任何帮助。提前感谢。
WebSecurityConfig.java 文件:

//WebSecurityConfig.java file

package com.example.demo.configuration;

import java.util.Arrays;
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.example.demo.services.AuthenticationProviderService;
import com.example.demo.filters.DtscCustomUsernamePasswordAuthenticationFilter;

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private DtscCustomUsernamePasswordAuthenticationFilter dtscCustomerUsernamePasswordAutenticationFilter;

    @Autowired
    private AuthenticationProviderService authenticationProvider;
    
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.cors().and().authorizeRequests()
        .antMatchers("/login").permitAll()
        .antMatchers("/").permitAll().anyRequest()
        .authenticated();
        http.addFilterAt(dtscCustomerUsernamePasswordAutenticationFilter, BasicAuthenticationFilter.class);   
    }
    
    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    }

DtscCustomUsernamePasswordAuthenticationFilter:

//DtscCustomUsernamePasswordAuthenticationFilter.java file

package com.example.demo.filters;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

    @Component
    public class DtscCustomUsernamePasswordAuthenticationFilter  extends OncePerRequestFilter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Value("${jwt.signing.key}")
    private String signingKey;

    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain   chain) throws ServletException, IOException {
        
        String username = null;
        String password = null;
        
        System.out.println(request);
            try{
                username = request.getParameter("username");
                password = request.getParameter("password");
                    System.out.println(username);
                    System.out.println(password);
        } 
        catch(Exception e) {
            throw new AuthenticationServiceException(e.getMessage(), e);
        }
        
        
        Authentication authRequest = new UsernamePasswordAuthenticationToken(username, password);
        authenticationManager.authenticate(authRequest);
        
        SecretKey key = Keys.hmacShaKeyFor(signingKey.getBytes(StandardCharsets.UTF_8));
        HashMap<String, Object> claims = new HashMap<>();
                claims.put("username", username);
        
        String jwt = Jwts.builder()
                .setClaims(claims)
                .signWith(key)
                .compact();
                response.setHeader("Authorization", jwt);    
        
                chain.doFilter(request, response);  
    }
    
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
    return !request.getServletPath().equals("/login"); }
    
    

}

AuthenticationProviderService:

//AuthenticationProviderService .java file
package com.example.demo.services;

import com.example.demo.respository.DtscUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

    @Component
    @Service
    public class AuthenticationProviderService implements AuthenticationProvider{
    @Autowired
    private DtscUserDetailsService dtscUserDetailsService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = authentication.getName();
            String password = String.valueOf(authentication.getCredentials());
            DtscUserDetails user = dtscUserDetailsService.loadUserByUsername(username);
            return checkPassword(user, password, bCryptPasswordEncoder);                
    }

    @Override
    public boolean supports(Class<?> aClass) {
            return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    }

    private Authentication checkPassword(DtscUserDetails user, String rawPassword, PasswordEncoder encoder) {
            if (encoder.matches(rawPassword, user.getPassword())) {
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(auth);
                return auth;
            } else {
                        throw new BadCredentialsException("Bad credentials");
                    }
    }

}

DtscUserDetailsService:

//DtscUserDetailsService.java file

package com.example.demo.services;

import com.example.demo.entities.DtscUser;
import com.example.demo.respository.DtscUserDetails;
import com.example.demo.respository.DtscUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.function.Supplier;

@Service
public class DtscUserDetailsService implements UserDetailsService{
     
    @Autowired
    private DtscUserRepository dtscUserRepository;
    
    @Override
        public DtscUserDetails loadUserByUsername(String username) {
          Supplier<UsernameNotFoundException> s = () -> new UsernameNotFoundException("Bad Credentials!");

            DtscUser u = dtscUserRepository.findDtscUserByUsername(username).orElseThrow(s);

            return new DtscUserDetails(u);
        }

}

DtscUserDetails:

//DtscUserDetails.java file

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.stream.Collectors;

public class DtscUserDetails implements UserDetails {

    private final DtscUser dtscUser;

    public DtscUserDetails(DtscUser dtscUser) {
        this.dtscUser = dtscUser;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return dtscUser.getListOfDtscAuthority().stream()
                   .map(a -> new SimpleGrantedAuthority(a.getUsername()))
                   .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return dtscUser.getPassword();
    }

    @Override
    public String getUsername() {
        return dtscUser.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public final DtscUser getUser() {
        return dtscUser;
    }
}
ds97pgxw

ds97pgxw1#

request.getParameter("username")将从querystring参数中提取username,而不是从给定的URL http://username:password@localhost:8090/login中提取。

**注意:**在URL中发送用户名和密码是安全流程,不推荐使用。始终使用POST请求,请求体中发送usename/password。

相关问题