关于Springboot2.x版本注解@ConfigurationProperties的使用

问题背景:

在工作中,通常会用到在yml配置文件中配置一些变量或者参数,在程序中使用的时候又不想使用@Value注解每个变量一个个导入,这个时候通常会使用@ConfigurationProperties注解,定义自定义变量配置类,根据参数前缀自动映射


问题描述

提示:下边是使用security配置类引入的yml变量的示例,但是使用@ConfigurationProperties映射配置文件变量失败,值为null:

jwt:
  url:
    skipAuthUrls: /api/v1/login/user/login
  secret: epdx
  expiration: 18000
  tokenHeader: Authorization
  loginFailMaxNum: 5
  tokenPrefix: authorization-
  authUserName: Authorization-UserName
  authRole: admin
  authEmail: [email protected]
package cn.isungent.ird.epdx.configuration;

import cn.isungent.ird.epdx.component.AuthenticationTokenFilter;
import cn.isungent.ird.epdx.component.RestAuthenticationEntryPoint;
import cn.isungent.ird.epdx.component.RestfulAccessDeniedHandler;
import cn.isungent.ird.epdx.component.UserAuthAccessDeniedHandler;
import cn.isungent.ird.epdx.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Collections;
import java.util.List;

/**
 * @author kiki
 * @date 2023/10/9
 * @description
 */
@Setter
@Configuration
@ConfigurationProperties(prefix = "jwt.url")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public String[] skipAuthUrls;



    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;

    @Autowired
    private IUserService iUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().logout().disable().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // 允许对于网站静态资源的无授权访问
                .and().authorizeRequests().antMatchers(HttpMethod.GET,
                "/*.html",
                "/favicon.ico",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js",
                "/swagger-resources/**",
                "/login/user/login/**",
                "/swagger-ui/**",
                "/v3/api-docs/**",
                "/v2/api-docs/**")
                .permitAll()
                // 对登录注册要允许匿名访问
                .antMatchers(skipAuthUrls)
                .permitAll()
                //跨域请求会先进行一次options请求
                .antMatchers(HttpMethod.OPTIONS)
                .permitAll()
                .anyRequest()
                // 除上面外的所有请求全部需要鉴权认证
                .authenticated();
        //添加自定义未授权和未登录结果返回
        http.exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint)
                .accessDeniedHandler(userAuthAccessDeniedHandler);
        // 禁用缓存
        http.headers().cacheControl();
        // 添加JWT filter
        http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加未授权处理
//        http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
        //权限不足处理
        http.exceptionHandling().accessDeniedHandler(userAuthAccessDeniedHandler);
    }

    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        //获取登录用户信息 从REDIS 访问 user-server模块 获取用户权限信息
        return username -> {
            User.UserBuilder userBuilder = User.builder();
            cn.isungent.ird.epdx.model.UserDO user = iUserService.getUserByUserName(username);
            if (user != null) {
                String[] grantedAuthorityList = null;
                userBuilder.username(username).password(user.getPassword()).accountExpired(false)
                        .accountLocked(false).disabled(false).credentialsExpired(false);
//                List privileges = iUserService.getUserAuthorityList(user.getId());
//                if (privileges != null) {
//                    grantedAuthorityList = privileges.stream().filter(p -> StringUtils.isNotBlank(p.getCode()))
//                            .map(Privilege::getCode).toArray(String[]::new);
//                }
                return userBuilder.authorities(grantedAuthorityList).build();
            }
            throw new UsernameNotFoundException("用户名或密码错误");
        };
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
    }

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

    @Bean
    public AuthenticationTokenFilter authenticationTokenFilter() {
        return new AuthenticationTokenFilter();
    }

    /**
     * 允许跨域调用的过滤器
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOriginPatterns(Collections.singletonList("*"));
        config.setAllowCredentials(true);
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return new CorsFilter(source);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setAllowUrlEncodedSlash(true);
        return firewall;
    }
}

原因分析:

主要是因为在使用@ConfigurationProperties时,使用变量的配置类,未为变量设置setter方法。
使用手动setXxx或者使用lombok注解@Setter均可

你可能感兴趣的:(spring,boot,java,Spring,spring,security,ioc)