Spring Security多种用户定义方式

news2024/12/26 23:37:26

本文内容来自王松老师的《深入浅出Spring Security》,自己在学习的时候为了加深理解顺手抄录的,有时候还会写一些自己的想法。

        Spring Security中存在两种类型的AutnenticationManager,一种是全局的AuthenticationManager,一种是局部的AuthenticationManager。局部的AuthenticationManager由HttpSecurity进行配置,而全局的AuthenticaitonManager可以不用配置,系统会提供一个默认的全局的AuthenticationManager对象。

        当进行用户身份认证时,首先会通过局部的AuthenticationManager对象进行验证,如果验证失败则会调用parent也就是全局的AuthenticaitonManager进行再次校验。ProviderManager类的authenticate方法中会判断如果没有AuthenticationProvider可以进行验证的话,就会调用parent的authenticate方法,也就是全局的AuthenticationManager进行身份验证。

        所以开发者在定义用户时,也分为两种情况:

  • 针对局部AuthenticationManager定义用户
  • 针对全局AuthenticationManager定义用户

针对局部AuthenticationManager定义用户

        为了演示方便,接下来我们使用InMemoryUserDetailsManager来构建用户对象,如果有小伙伴想把用户信息存在数据库可以参考之前的用MyBatis加载用户信息。

        正对局部AuthenticationManager定义用户:

/**
 * @author tlh
 * @date 2022/11/21 21:50
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("test1").password("{noop}123").authorities("test").build());
        manager.createUser(User.withUsername("test").password("{noop}456").authorities("test").build());
        http.authorizeRequests((requests) -> ((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl) requests.anyRequest()).authenticated());
        http.formLogin().successForwardUrl("/hello").permitAll();
        http.userDetailsService(manager);
        http.httpBasic();
    }
}

        在上面的代码中,我们基于内存来管理用户,并向manager中添加了两个用户,将配置好manager对象添加到了HttpSecurity中,也就是配置到了了局部的AuthenticaitonManager中。

        配置完成之后,启动项目我们使用test1和test输入我们设置的密码就可以正常登陆系统了。但是,小伙伴们注意下我们在启动项目时,IDEA控制台的日志中看到如下内容:

         通过前面的学习我们知道这个是系统自动为我们生成的用户。当然我们通过系统自动生成的用户信息来登录也是可以正常登录的。系统自动提供的用户对象实际上是往Spring IOC容器汇总注册了一个InMemoryUserDetailsManager对象来实现。实际上,系统提供的用户相关于全局AuthenticationManager对应的用户。

        以上面的代码为例,当我们执行登录后,Spring Security首先会调用局部的AuthenticationManager去进行登录校验,如果用户名和密码是test1/123或者test/456那就直接登录成功,否则登录失败。当登录失败后系统会调用局部的AuthenticationManager的parent也就是全局的AuthenticationManager继续校验,此时登录用户和密码是user/c482358e-1464-4d0a-aece-3dde04d79dcd,则登录成功,否则登录失败。

针对全局AuthenticationManager定义用户

        下来来我们就正对全局的AuthenticationManager来设置用户信息。由于默认全局的AuthenticationManager在配置的时候会从Spring的IOC容器中查找UserDetailsService实例,所以我们如果想要在针对全局AuthenticationManager配置用户,只需要往Spring IOC容器中注入一个UserDetailsService实例即可:

/**
 * @author tlh
 * @date 2022/11/21 21:50
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //全局
    @Bean
    @Primary
    UserDetailsService users1() {
        return new InMemoryUserDetailsManager(User.builder().username("javaBody").password("{noop}123").roles("admin").build());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //局部
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("test1").password("{noop}123").authorities("test").build());
        manager.createUser(User.withUsername("test").password("{noop}456").authorities("test").build());
        http.authorizeRequests((requests) -> ((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl) requests.anyRequest()).authenticated());
        http.formLogin().successForwardUrl("/hello").permitAll();
        http.userDetailsService(manager);
        http.httpBasic();
    }
}

        配置完成后,当我们启动项目时,全局的AuthenticationManager在配置时会去Spring容器中查找UserDetailsService实例,找到的就是我们定义的UserDetailsService。接着不仅可以使用test1和test登录了,还可以使用javaBody登录。

        当然,小伙伴们也可以通过从写WebSecurityConfigurerAdapter的configure(AuthenticationManagerBuilder auth)方法来自定义全局AuthenticaitonManager对象:

/**
 * @author tlh
 * @date 2022/11/21 21:50
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


//    //全局
//    @Bean
//    @Primary
//    UserDetailsService users1() {
//        return new InMemoryUserDetailsManager(User.builder().username("javaBody").password("{noop}123").roles("admin").build());
//    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.inMemoryAuthentication().withUser("javagirl")
                .password("{noop}123")
                .roles("admin");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //局部
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("test1").password("{noop}123").authorities("test").build());
        manager.createUser(User.withUsername("test").password("{noop}456").authorities("test").build());
        http.authorizeRequests((requests) -> ((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl) requests.anyRequest()).authenticated());
        http.formLogin().successForwardUrl("/hello").permitAll();
        http.userDetailsService(manager);
        http.httpBasic();
    }
}

        还有,如果我们重写了WebSecurityConfigurerAdapter的configure(AuthenticationManagerBuilder auth)方法,那么全局的AuthenticationManager对象将以configure(AuthenticationManagerBuilder auth)方法中定义的用户为准。此时如果我们向Spring的IOC容器中注入另外一个UserDetailsService实例也不会生效。

小结

        Spring Security中几种不同的用户定义方式,通过这个几个案例,小伙伴们对全局的AuthenticationManager和局部的AuthenticationManager对象会有更加深刻的认识了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

原版畅销36万册!世界级网工打造TCP/IP圣经级教材,第5版终现身

关于TCP/IP 现代网络中,以窃取信息或诈骗为目的的网站频频出现,蓄意篡改数据以及信息泄露等犯罪行为也在与日俱增。很多情况下,人们可能会认为人性本善,在享受着网络所带来的便捷性的同时,也就降低了对网络犯罪的设防…

深入理解java虚拟机:类文件结构(2)

文章目录Class类文件结构2.6 方法表集合2.7 属性表集合3. Class文件结构的发展Class类文件结构 接着上一篇,我们继续补充 2.6 方法表集合 Class文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式,方法表的结构如同字段表一样&#x…

算法设计与分析 SCAU17964 水桶打水

17964 水桶打水 时间限制:1000MS 代码长度限制:10KB 提交次数:25 通过次数:9 题型: 编程题 语言: G;GCC;VC;JAVA Description 有n个人&#xff08;n<100000&#xff09;带着大大小小的水桶容器&#xff08;每人一个水桶&#xff09;排队到r个&#xff08;r<1000&#…

JS基础习题

1.JavaScript变量命名规则 1.在JavaScript中以下&#xff0c;以下哪些变量名是非法的&#xff08;会导致程序报错&#xff09;&#xff1f; 1person name var $orderwera23 uiuiuqwer4_23aser2 A .1person&#xff0c;name B .name&#xff0c;var C .$orderwera23&#xff0c…

怎么自制小程序?【自己制作小程序】

说到制作小程序&#xff0c;有些动手能力比较强的小伙伴可能就在想怎么自制小程序。想自制小程序&#xff0c;至少也是需要会一些编程代码的&#xff0c;如果不懂代码就只能找其他方法了。那么怎么自制小程序呢&#xff1f; 现在市面上有很多的小程序制作工具&#xff0c;可以…

hexo建站新手入门

Hexo是一款基于Node.js的静态博客框架&#xff0c;依赖少易于安装使用&#xff0c;可以方便的生成静态网页托管在GitHub和Coding上&#xff0c;是搭建博客的首选框架。 hexo史上最全搭建教程 Hexo搭建步骤 安装Git安装Node.js安装HexoGitHub创建个人仓库生成SSH添加到GitHub…

几分钟让你了解Linux下文件权限掩码及作用

在说文件权限掩码之前&#xff0c;必须了解下linux下的文件权限&#xff0c;比如在linux下可以通过“ls -l”命令查看文件的权限&#xff0c;输入后可以获得如下显示&#xff1a; drwxrwxr-x 3 linux linux 4096 Jun 6 18:03 test 在显示中“drwxrwxr-x”这十个字母中第一个字母…

数据分析入门必看|数据分析到底应该学什么?

数据分析在工作和学习中用到的越来越多&#xff0c;以前也成体系的分享了一些内容&#xff0c;详情参考链接&#xff1a;数据分析系列 1/32 | 数据分析入门理解。在之前的分享内容里&#xff0c;是为了让大家更快上手入门去学习使用的&#xff0c;本次内容合计里&#xff0c;每…

知乎转发最高的 Java 面试成神笔记,GitHub 已下载量已过百万

在某论坛上面对于“中国程序员数量是否已经饱和或者过剩”这个话题很火&#xff01; 今年大家都有一个共同的感受&#xff1a;工作不好找&#xff0c;薪资不理想&#xff0c;面试造火箭。 其实&#xff0c;由于不仅是因为今年受疫情影响&#xff0c;很多公司经营不下去&#xf…

防不胜防?网络钓鱼攻击常用手法盘点与防护建议

【环境搭建资料、工具包、全套视频…等籽料】私信聆取 网络钓鱼攻击是最常见、最容易让受害者中招的网络犯罪之一&#xff0c;随着网络技术的不断发展&#xff0c;攻击者的伪装手段也变得愈发狡诈&#xff0c;攻击频次也再增高&#xff0c;各种新奇的攻击方式层出不穷。有些攻…

day30 SQL注入CTF二次堆叠DNS带外

二次注入 原理 二次注入是存储型注入&#xff0c;可以理解为构造恶意数据存储在数据库后&#xff0c;恶意数据被读取并进入到了SQL查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中&#xff0c;当Web程序调用存储在数据库中的恶意数据并执行…

成都地区一汽大众汽车4s店营销策略研究

目 录 第一章 绪论 1 1.1选题及意义 1 1.2 国内外现状 1 1.3研究主要内容 3 1.4研究方法 3 第二章 成都地区一汽大众汽车4S店营销市场调查分析 4 2.1调查目的 4 2.2调查过程 4 2.3数据分析与调查结果 4 2.4启示与思考 8 第三章 成都地区一汽大众汽车4S店SWOT分析 9 3.1成都地区…

过五关,斩六将!「网易/美团/菜鸟」已拿offer【Java岗】

经过两个月的辛苦奋战&#xff0c;最终拿到了网易、头条、字节、菜鸟的offer&#xff0c;感觉面试的时候还是很幸运的&#xff0c;很多题都是我之前刷题刷到过的&#xff0c;哈哈哈~~下面给广大网友们分享一下我的面经&#xff08;网易/美团/菜鸟&#xff09;供大家参考参考...…

python教程:*的用法,你可能错过了......

人生苦短&#xff0c;我用python python中*是非常常见的一个运算符&#xff0c;它主要有以下几个功能&#xff1a; 乘法运算符&#xff1b; 函数形参表示可变参数&#xff1b; 函数实参代表tuple&#xff1b; 序列解包为tuple&#xff1b; zip解包运算&#xff1b; 更多学习干…

SpringCloud学习笔记 - 消息总线 - Spring Cloud Bus

1. 消息总线简介 消息代理中间件构建了一个共用的消息主题让所有微服务实例订阅&#xff0c;当该消息主题产生消息时会被所有微服务实例监听和消费。 消息代理又是什么&#xff1f;消息代理是一个消息验证、传输、路由的架构模式&#xff0c;主要用来实现接收和分发消息&…

Java EE|进程与线程的区别与联系

大数据时代&#xff0c;数据规模非常庞大&#xff0c;所以我们在实际开发过程中&#xff0c;需要经常进行并发问题的处理。对于此问题&#xff0c;我们通常有两种解决方案&#xff1a;多进程方式和多线程方式。但是由于多进程对于资源的共享非常困难&#xff0c;而多线程并发可…

一个宁静祥和没有bug的下午和SqlSession的故事

作者&#xff1a;马跃 1 背景 这是一个安静祥和没有bug的下午。 作为一只菜鸡&#xff0c;时刻巩固一下基础还是很有必要的&#xff0c;如此的大好时机&#xff0c;就让我来学习学习mybatis如何使用。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(i…

模拟退火--学习笔记

模拟退火算法来源&#xff1a; 固体退火原理&#xff0c;将固体加温至充分高&#xff0c;再让其徐徐冷却&#xff0c;加温时&#xff0c;固体内部粒子随温升变为无序状&#xff0c;内能增大&#xff0c;而徐徐冷却时粒子渐趋有序&#xff0c;在每个温度都达到平衡态&#xff0c…

【图神经网络论文整理】(三)—— HOW TO FIND YOUR FRIENDLY NEIGHBORHOOD:SuperGAT

ICLR 2021Dongkwan Kim & Alice Oh论文地址 本文介绍的论文是《HOW TO FIND YOUR FRIENDLY NEIGHBORHOOD: GRAPH ATTENTION DESIGN WITH SELF-SUPERVISION》。 该篇论文提出了一个新的网络模型SuperGAT&#xff0c;目的是解决当图中存在噪声能够学习到更多的表达注意力&a…

实体店做微信商城小程序制作步骤_分享微信商城小程序的作用

各行各业都在用微商城小程序开店&#xff0c;不管是餐饮店还是便利店&#xff0c;还是五金店。都是可以利用微信小程序开一个线上店铺。实现线上跟线下店铺更加全面的结合。维护好自己的老客户。让您的客户给您拉新&#xff0c;带来新客户。 小程序经过这几年的快速发展和不断升…