在工作中,通常会用到在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均可