文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Security在6.0弃用WebSecurityConfigurationAdapter后该如何自定义配置介绍(新旧示例)

2023-08-17 06:23

关注
在本人经历过新版和旧版的不同的配置折磨后,决心自己写一篇介绍造福大众,不好地方,欢迎伙指出ovo本文针对Spring Security 6.0版本的自定义配置进行介绍,其中包含自定义数据源UserDetailsService、自定义过滤链SecurityFilterChain等内容.

1.旧版

在旧版的配置中,Security需要我们写一个类去继承他的WebSecurityConfigurerAdapter并把这个配置注入到容器中

@Configurationpublic class WebSecurityConfigurer extends WebSecurityConfigurerAdapter{.....}

在继承这个类后,我们可以在WebSecurityConfigurer里面去重写WebSecurityConfigurationAdapter类里面的一些方法来实现自定义过滤链等操作
Alt
实现自定义过滤链需要重写configure(HttpSecurity http)方法

@Override    protected void configure(HttpSecurity http) throws Exception {    http    .mvcMatchers("/login.html")    .permitAll()    .formLogin()    .......csrf().disable();                }
这个方法的参数http采用的是链式设计,我们直接 ‘.’就可以进行设置。

特别的在旧版的配置中,我们需要手动将AuthenticationManager类暴露在全局中,使我们能在其他功能实现上可以拿到这个认证管理器

// 暴露认证管理器给全局    @Override    @Bean    public AuthenticationManager authenticationManagerBean()            throws Exception {        return super.authenticationManagerBean();    }

旧版整体代码

@Configuration// Security自定义配置器"public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {@Override    protected void configure(HttpSecurity http) throws Exception {    http    .mvcMatchers("/login.html")    .permitAll()    .formLogin()    .......csrf().disable();                }    @Override    @Bean    public AuthenticationManager authenticationManagerBean()            throws Exception {        return super.authenticationManagerBean();    }}

2.新版

在新版的Spring Security里面,如果我们继续继承WebSecurityConfigurationAdapter类的话,会出现如下弃用提示

public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter

在新版中我们只需要在自定义的配置类头顶添加一个 @EnableWebSecurity 注解即可将你写的这个注入到IOC容器中

该注解源码如下:

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,HttpSecurityConfiguration.class })@EnableGlobalAuthentication@Configurationpublic @interface EnableWebSecurity {boolean debug() default false;}

从源码中我们可以看到内部以及实现了@Configuration注解,所有不需要我们手动注入IOC容器

在这个注解内部,作者也对新版的Spring Security配置SecurityFilterChain进行了特别说明
在这里插入图片描述

其中我们目前只需要注意securityFilterChain(HttpSecurity http)这个方法,这个方法就是我们配置自定义过滤链需要实现的方法

以下是实现伪代码

@Bean    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {        http                .authorizeHttpRequests((auth) -> {                    auth.mvcMatchers("/user/login").permitAll().anyRequest().authenticated();                })                .formLogin()                ......                .csrf()                .disable()             // 构建过滤链并返回return http.build();     }

新版的实现方法不再和旧版一样在配置类里面重写方法,而是构建了一个过滤链对象并通过@Bean注解注入到IOC容器中

新版整体代码 (注意:新版AuthenticationManager认证管理器默认全局

@EnableWebSecurity// Security自定义配置器public class WebSecurityConfiger     {@Bean    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {        http                .authorizeHttpRequests((auth) -> {                    auth.mvcMatchers("/user/login").permitAll().anyRequest().authenticated();                })                .formLogin()                ......                .csrf()                .disable()             // 构建过滤链并返回return http.build();     }}

在介绍如何配置前,我们先来看看底层是如何进行数据源认证的,下面是流程图:认证流程
在整个认证流程中,我们在提交用户表单数据的时候,会先被AbstractAuthenticationProcessingFilte捕获到如何被封装为UsernamePasswordAuthenticationToken 的token 对象,然后将整个对象交给AuthenticationManager认证管理器去实现认证,而这个时候就会去数据源UserDetailService类中去进行对应的认证方式,认证成功返回UserDetails对象,否则返回null,所以我们这个时候目的就比较明确了,为实现自定义数据源,我们就需要去重新实现一个类继承自UserDetailsSerive类,然后将这个类交给AuthenticationManager认证管理器,这样我们在认证的时候,认证管理器就会使用我们自定义的数据源

那么在新旧版本又是如何进行配置的,我们往下看

1.旧版

在旧版的配置中,我们首先去实现一个自定义实体类继承自UserDetails(注意:必须把这个类需要重写一些方法,这些方法都是给认证管理器去做一些工作的,这个User类还可以拥有一些其他的字段属性,比如说username,password…建议基于数据库中的User表来设置

@Data//@ApiModel(value = "User对象", description = "用户对象")public class User implements UserDetails {private String username;private String password;.....@Override    @JsonIgnore    public Collection getAuthorities() {        // 创建角色集合        .........        return grantedRoles;    }    @Override    @JsonIgnore    public boolean isAccountNonExpired() {        return true;    }    @Override    @JsonIgnore    public boolean isAccountNonLocked() {        return true;    }    @Override    @JsonIgnore    public boolean isCredentialsNonExpired() {        return true;    }    @Override    @JsonIgnore    public boolean isEnabled() {        return true;    }}

然后是实现一个类继承UserDetailsService (注意我代码使用了mp查询数据,非mp正常在UserMapper里面写对应SQL,只要将最终查询到的用户User返回即可)

在这个类中,我们也使用了@Component注解将这个数据源交给IOC容器

@Component// "登录数据源"public class LoginUserDetailService implements UserDetailsService {// 数据库查询User信息    private final UserMapper userMapper;private final RoleMapper RoleMapper    @Autowired    public LoginUserDetailService(UserMapper userMapper, RoleMapper roleMapper) {        this.userMapper = userMapper;        this.roleMapper = roleMapper;    }    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        // 查询用户        LambdaQueryWrapper queryWrapper_User = new LambdaQueryWrapper<>();        queryWrapper_User.eq(User::getUsername,username);        User user = userMapper.selectOne(queryWrapper_User);        // 工具类判断是否查询user对象是否有效        if (ObjectUtils.isEmpty(user)) {            throw new UsernameNotFoundException("用户不存在");        }        LambdaQueryWrapper queryWrapper_Role = new LambdaQueryWrapper<>();        queryWrapper_Role.eq(Role::getUid,user.getId());        List roles = roleMapper.selectList(queryWrapper_Role);        user.setRoles(roles);        // User类继承了UserDetails,返回时会进行向上转型,所以我们将正常查询到的user数据装进User对象返回即可        return user;    }}

现在到最后一步了,回到我们的WebSecurityConfigurationAdapter实现类里面,我们使用@Autowired注入我们刚刚写的LoginUserDetailService类使用 configure(AuthenticationManagerBuilder auth) 方法将这个实例交给AuthenticationManager,下面是具体代码

@Configurationpublic class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {   @Autowired   private LoginUserDetailService loginUserDetailService      @Override   protected void configure(HttpSecurity http) throws Exception {   http   .mvcMatchers("/login.html")   .permitAll()   .formLogin()   ......   .csrf()   .disable();   }      @Override   protected void configure(AuthenticationManagerBuilder auth) throws Exception {   auth.userDetailsService(loginUserDetailService);   }      @Override   @Bean   public AuthenticationManager authenticationManagerBean()           throws Exception {       return super.authenticationManagerBean();   }}

2.新版

新版的比较简单,直接定义好数据源,注入就可以了,无需手动到配置类中去将它提交给AuthenticationManager进行管理。

@Componentpublic class LoginUserDetailService implements UserDetailsService {    private final UserMapper userMapper;    @Autowired    public LoginUserDetailService(UserMapper userMapper, RoleMapper roleMapper) {        this.userMapper = userMapper;    }    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {          // 数据查询      userMapper.方法                return user;    }}

相比旧版,跳过了手动auth.userDetailsService(loginUserDetailService),新版底层会帮你执行这一步

=THE END=

来源地址:https://blog.csdn.net/weixin_59216829/article/details/130098599

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯