关于“详解springSecurity之java配置篇”完整攻略,我们来详细说一下。
简介
SpringSecurity是基于Spring框架的安全框架,主要解决的是在应用程序中如何安全地进行身份认证和授权。本篇文档主要讲解如何使用Java配置的方式来进行SpringSecurity的配置。
步骤
1. 添加spring-security配置依赖
在 pom.xml 文件中添加如下依赖:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.5.1</version>
</dependency>
2. 配置SpringSecurity基础信息
- 实现 SecurityConfigurerAdapter 类来进行基础 SpringSecurity 配置。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/**").authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
这里使用了 HttpSecurity
来定义如何配置应用程序的各个安全性方面,配置了请求的访问权限和请求的登录页,以及自定注销功能和禁用跨域请求伪造。
- 配置 UserDetailsService 的实现
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return new SecurityUser(user);
}
}
其中,SecurityUser
是实现 SpringSecurity 的 UserDetails
接口的一个类,用于对数据库中存储的用户密码进行加密。
public class SecurityUser extends User implements UserDetails {
private static final long serialVersionUID = -5032883717944428014L;
public SecurityUser(User user) {
if(user != null) {
this.setUsername(user.getUsername());
this.setPassword(user.getPassword());
this.setEnabled(user.getEnabled());
this.setAccountNonExpired(user.getAccountNonExpired());
this.setAccountNonLocked(user.getAccountNonLocked());
this.setCredentialsNonExpired(user.getCredentialsNonExpired());
this.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));
}
}
}
3. 配置 SpringSecurity SessionHandlingFilter
在配置基础信息的同时,还需要处理 SpringSecurity 的 session 管理,根据情况对 SessionHandlingFilter 进行自定义调整。
3.1. 配置 SessionCreationPolicy
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
...
}
}
这里使用 SessionCreationPolicy.STATELESS
来表示不创建 session。
3.2. 自定义 SessionManagementFilter
public class CustomSessionManagementFilter extends SessionManagementFilter {
public CustomSessionManagementFilter(SessionAuthenticationStrategy sessionAuthenticationStrategy) {
super(new NullAuthenticatedSessionStrategy(), new HttpSessionSessionStrategy());
this.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
}
对于 SessionManagementFilter
,这里使用了自定义 CustomSessionManagementFilter
来扩展 SessionManagementFilter
的基础功能。
4. 配置SpringSecurity FilterChainProxy
- 添加WebApplicationInitializer实现类
public class SecurityWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[0];
}
@Override
protected String[] getServletMappings() {
return new String[0];
}
}
- 添加SecurityFilterChain
public class SecurityWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[0];
}
@Override
protected String[] getServletMappings() {
return new String[0];
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
filterProxy.setTargetBeanName("springSecurityFilterChain");
return new Filter[]{
encodingFilter, filterProxy
};
}
}
示例
这里列出两个简单的例子,可以了解如何在 Spring Boot 中 (举例)实现基于 Java 配置的 Spring Security。
示例1:基本使用
配置 SpringSecurity 基础信息:
@Configuration
@EnableWebSecurity
public class BasicSecSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/console/**").permitAll()
.antMatchers("/api/**").permitAll()
.antMatchers(HttpMethod.POST, "/signup").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll();
http.csrf().disable();
http.headers().frameOptions().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("{noop}password").roles("ADMIN");
}
}
@Configuration
public class BasicSecWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{BasicSecSecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
示例2:记住我功能
```java
@Configuration
@EnableWebSecurity
public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username,password,enabled from users where username=?")
.authoritiesByUsernameQuery("select username, role from user_roles where username=?")
.passwordEncoder(passwordEncoder());
}
private PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.rememberMe()
.key("privatekey")
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60*60*24*7)
;
http.csrf().disable();
}
@Bean
public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices("privatekey", userDetailsService(), persistentTokenRepository());
return tokenBasedservice;
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
db.setDataSource(dataSource);
return db;
}
@Override
public UserDetailsService userDetailsService() {
return new JdbcUserDetailsManager(dataSource);
}
}
@Configuration
public class RememberMeWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.scan("com.journaldev.spring");
sc.addListener(new ContextLoaderListener(root));
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.scan("com.journaldev.spring");
ServletRegistration.Dynamic dispatcher = sc.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
FilterRegistration.Dynamic fr = sc.addFilter("encodingFilter", CharacterEncodingFilter.class);
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");
FilterRegistration.Dynamic fr1 = sc.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
fr1.setInitParameter("targetBeanName", "springSecurityFilterChain");
fr1.addMappingForUrlPatterns(null, true, "/*");
}
}
这里使用了 remember me
功能,用户登录时,可以选择是否让系统记住自己的 credentials,并在下次会话中自动登录。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解springSecurity之java配置篇 - Python技术站