详解springSecurity之java配置篇

关于“详解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技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 总结Java常用排序算法

    总结Java常用排序算法 算法简介 排序算法是计算机程序设计中最基本的问题之一,它的目的是将一组“无序”的数据,按照某种规律进行排列。在Java中,常用的排序算法有如下几种: 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 冒泡排序 冒泡排序是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就将它们交换过…

    Java 2023年5月19日
    00
  • java开发MyBatis中常用plus实体类注解符详解

    Java开发MyBatis中常用Plus实体类注解符详解 什么是MyBatis Plus? MyBatis Plus是MyBatis的一个增强工具,在MyBatis基础之上进行扩展。MyBatis Plus提供了很多实用的增强功能,如分页查询、条件构造器、逻辑删除、自动填充等,使得开发人员可以更加快捷地编写代码。在MyBatis Plus中,实体类注解符是其…

    Java 2023年5月20日
    00
  • 关于maven环境的安装及maven集成idea环境的问题

    下面是关于maven环境的安装及maven集成idea环境的问题的完整攻略。 1. Maven环境的安装 1.1 下载Maven 首先,需要从Maven官网上下载最新版的Maven。可以访问以下网址: https://maven.apache.org/download.cgi 选择最新版本的二进制zip文件,下载后解压缩到本地。 1.2 配置环境变量 在Ma…

    Java 2023年5月20日
    00
  • 在JavaScript中使用for循环的方法

    在 JavaScript 中,for 循环用于重复执行某些代码。for 循环通常用于遍历数组或对象,执行相同的代码多次。 基本格式为: for (初始值; 终止条件; 增量) { // 要执行的代码块 } 其中: 初始值:定义用于循环计数的变量,并设置初始值。 终止条件:定义循环运行条件,如果该条件为 true,则循环继续执行;如果为 false,则循环结束…

    Java 2023年5月26日
    00
  • Java线程中sleep和wait的区别详细介绍

    下面详细讲解Java线程中sleep和wait的区别。 sleep和wait的区别 等待方式不同 sleep()方法是线程的静态方法,通过该方法可以使当前线程暂停指定的时间,但不会释放已经持有的锁。wait()方法是Object类中的方法,通过该方法可以使线程等待其它线程通知其被唤醒,同时会释放当前持有的锁。 调用位置不同 sleep()方法可以在任何位置调…

    Java 2023年5月19日
    00
  • mysql如何创建数据库并指定字符集

    mysql如何创建数据库并指定字符集? 在MySQL中,可以使用CREATE DATABASE命令来创建新的数据库,同时可以通过指定COLLATE选项来指定数据库所使用的字符集。下面是完整的创建数据库并指定字符集的攻略: 步骤1:登录MySQL 要使用MySQL的命令行工具来创建数据库,首先需要登录到MySQL。可以使用以下命令来登录到MySQL: mysq…

    Java 2023年5月20日
    00
  • Java如何实现支付宝电脑支付基于servlet版本

    Java 如何实现支付宝电脑支付基于 Servlet 版本,具体的实现步骤如下: 1. 注册支付宝商家账号 首先需要注册一个支付宝商家账号。 2. 下载支付宝开发者工具包 下载支付宝提供的开发者工具包,官方推荐使用 Java 版本的 SDK。 3. 创建订单 在进行支付前需要创建一个订单,在创建订单时需要填写订单的一些基本信息,例如订单金额、商品名称、订单号…

    Java 2023年5月26日
    00
  • Mybatis实现自动生成增删改查代码

    下面我给你详细讲解一下Mybatis实现自动生成增删改查代码的完整攻略。 概述 Mybatis是一款基于Java的持久层框架,它提供了自动生成增删改查代码的功能,让开发人员可以快速生成常用的CRUD操作。可以大大提高代码的开发效率,减少了数据库访问层的开发工作量。 步骤 实现Mybatis自动生成增删改查代码的过程如下: 配置Mybatis Generato…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部