【问题标题】:Spring Boot problem trying to verify if user is logged or not for any activity尝试验证用户是否已记录任何活动的 Spring Boot 问题
【发布时间】:2021-02-23 06:11:42
【问题描述】:

Holla 开发人员,我正在尝试使用 maven 作为包装器在我的应用程序上构建 Spring 安全流程,现在我很困惑如何设置有关用户是否登录的验证以触发特定功能在我的一个控制器上,假设在我的 SecurityConfig 文件中我设置了这个:

...some imports....

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    RenterService renterService;
    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public Authentication authentication(){
        return authentication();
    }


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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/cubancoder/multirenter/**","/v2/api-docs","/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**").permitAll()
                .antMatchers("/api/test/**").permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }


}

然后假设我启用了一项服务及其实现以通过我的控制器获取所有产品

服务:


...some imports...

public interface ProductService {
    Map<String,Object> getAllProducts()throws GeneralException;
}

服务实施:

...some imports...



@Service
public class ProductServiceImpl implements ProductService{


    public static final ModelMapper modelMapper = new ModelMapper();
    @Autowired
    ProductRepository productRepository;

    @Autowired
    ProductDtos productDtos;

    @Autowired
    AuthenticationValidation securityApp;

    @Autowired
    RenterDtos renterDtos;

    @Autowired
    RenterRepository renterRepository;

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    public Map<String,Object> getAllProducts() throws GeneralException {
        Map<String,Object>dto=new HashMap<>();

        List<Product>listProducts=productRepository.findAll();

        if(auth==null){
            dto.put("renter",null);//IF NO ONE IS LOGGED

        }
        else{
            dto.put("renter",renterDtos.makeRenterDto(securityUser(auth)));IF THER IS A USER LOGGED
        }
        dto.put("list_ofProducts", listProducts.stream().map(service->productDtos.makeProductDto(service)).collect(Collectors.toList()));
   
        return dto;
    }

    private  Renter securityUser(Authentication auth)throws NotFoundException {

        return renterRepository.findByRenterName(auth.getName()).orElseThrow(()->new NotFoundException("SError","EmailNotFound"));
    }


}


无论用户是否登录,总是落在用户为空

     if(auth==null){
            dto.put("renter",null);//IF NO ONE IS LOGGED

     }

关于如何改善这种情况的任何想法? 提前致谢!!

【问题讨论】:

    标签: java spring-boot authentication spring-security


    【解决方案1】:

    问题是ProductServiceImpl 的单个实例在启动时正在初始化auth,而SecurityContextHolder 中没有用户。相反,您应该在确保auth 变量在请求时初始化的方法中初始化auth,并且每个请求都有一个唯一的auth 实例(避免竞争条件)。像这样的:

    @Service
    public class ProductServiceImpl implements ProductService{
    
    
        public static final ModelMapper modelMapper = new ModelMapper();
        @Autowired
        ProductRepository productRepository;
    
        @Autowired
        ProductDtos productDtos;
    
        @Autowired
        AuthenticationValidation securityApp;
    
        @Autowired
        RenterDtos renterDtos;
    
        @Autowired
        RenterRepository renterRepository;
    
        // remove auth as a member variable because it will be a shared variable across all requests and is null when the class initializes at startup
    
        public Map<String,Object> getAllProducts() throws GeneralException {
            // initialize auth as a stack variable so that it is no longer shared across requests and it is initialized when a user is in context (at request time)
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
           ...
        }
    // ...
    }
    

    【讨论】:

    • Holla Rob ...确实尝试过您的建议,但仍然给我带来麻烦...您能再解释一下吗?
    • 应用你的逻辑让我立即在私有方法“securityUser”的未找到异常中,不让我将 dto 暴露为租户 null
    • 这似乎回答了您关于如何解决Authentication 的问题。如果是这样,你能把它标记为正确答案吗?如果没有,你能解释一下发生了什么吗?
    • 其他人发现这很有用......而且我很确定我省略了一些东西。但是正如我告诉你的那样,一旦我应用了你的代码,我就得到了进入私有函数 SecurityUser 例外的函数
    猜你喜欢
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2019-02-13
    • 2019-01-13
    • 2014-12-31
    相关资源
    最近更新 更多