Spring Security入门demo案例

目录
  • 一、简介
  • 二、入门案例
  • 三、自定义认证逻辑
  • 四、自定义授权逻辑
  • 五、注销登录
  • 六、记住我功能
  • 七、会话管理

一、简介

Spring Security是一个高度自定义的安全框架。利用Spring IoC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。主要包含如下几个重要的内容:

  • 认证(Authentication),系统认为用户是否能登录。
  • 授权(Authorization),系统判断用户是否有权限去做某些事情。

二、入门案例

首先引入必要的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

然后创建一个controller:

@Slf4j
@RestController
public class SecurityController {

    @GetMapping({"/", "/index"})
    public String getLogin() {
        log.info("进入index");
        return "index";
    }

}

此时,我们的入门案例就完成了。启动项目,Spring Security默认就开启了,此时访问localhost:8080/index就会被Spring Security拦截,跳转到内置的登录页面要求登录。

默认情况下,登录的用户名为user,密码在启动项目的时候,控制台有打印出来:

Using generated security password: 0bfad04b-7a47-40fb-ae15-2a4a7c57099b

使用如上的账密登录后,再次访问localhost:8080/index就可以正常返回预期的内容index了。

如果我们不希望使用默认的用户密码,可以在配置文件中指定一个,如此Spring Security就会使用我们指定的,而不会使用默认的了。

spring.security.user.name=zhangxun
spring.security.user.password=123123

三、自定义认证逻辑

当我们开启自定义认证逻辑后,上面的默认用户和配置文件中的用户就不生效了,可以先行删除。

我们新建一个MySecurityConfig类,并继承WebSecurityConfigurerAdapter类,用于自定义认证逻辑。

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 指定使用BCryptPasswordEncoder对前端传过来的明文密码进行encode
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        // 用户的真实密码需要encode,security是比较两个密文是否一致
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("root").password(encoder.encode("root123")).roles();
    }

}

需要注意的是,密码必须使用如上的PasswordEncoder进行编码,否则会抛出如下错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

此时,我们重启应用,访问localhost:8080/index进入内置的登录页面,输入root/root123之后就能正常返回index内容了。

四、自定义授权逻辑

一般权限管理都是基于RBAC模型的,即登录的用户肯定拥有某些角色,这些角色允许访问某些资源。我们先来改造下认证的逻辑:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("root").password(encoder.encode("root123")).roles("admin","manager")
        .and()
        .withUser("manager").password(encoder.encode("mm000")).roles("manager");
}

使得root用户拥有admin和manager两个角色,zhang用户拥有manager一个角色。

然后我们在该配置类中再增加自定义授权的逻辑:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        // 任何角色允许访问
        .antMatchers("/", "/index").permitAll()
        // 仅admin角色可以访问
        .antMatchers("/admin/**").hasRole("admin")
        // admin和manager两个角色可以访问
        .antMatchers("/manager/**").hasAnyRole("admin", "manager");

    // 没有权限则进入内置的登录页面
    http.formLogin();
}

然后为了测试,我们还需要增加几个资源:

@Slf4j
@RestController
public class SecurityController {

    @GetMapping({"/", "/index"})
    public String getLogin() {
        log.info("进入index");
        return "index";
    }

    @GetMapping("admin/getHello")
    public String getAdminHello(){
        return "hello admin!";
    }

    @GetMapping("manager/getHello")
    public String getManagerHello(){
        return "hello manager!";
    }

    @GetMapping("guest/getHello")
    public String getGuestHello(){
        return "hello guest!";
    }

}

此时,重启项目,我们发现:

  • 访问/,/index,/guest/**的资源直接就能返回,不需要认证和授权。
  • 访问/admin/**资源的时候,由于没有登录,会跳转到内置的登录页面;如果已经登录,只有root用户登录后才可以访问;
  • 访问/admin/**资源的时候,由于没有登录,会跳转到内置的登录页面;如果已经登录,那么root和zhang用户都能访问;

我们还可以定制自己的登录页面,用于替换Spring Security内置的登录页面,这块需要定制html页面,本文不再详述,比较简单,可以参考formLogin的源码注释,里面讲的比较清楚。

五、注销登录

因为我们使用的是Spring Security内置的登录页面,各个资源返回的也是json字符串,并非页面,所以如何实现注销登录是个问题。但可以通过阅读HttpSecurity:logout中的源码注释,我们基本就能学会怎么操作了。

  • 注销登录默认就开启了,默认是访问/logout,和/login一样都是Spring Security自己实现的,我们调用即可;
  • 注销登录会清除服务器端的session,清除remember me等设置;这个后面再详细解说;
  • 注销登录后默认会跳转到/login页面;

还是如上的案例,我们在登录后,直接调用http://localhost:8080/logout就可以实现上述的注销登录功能了。

但是在有些时候,我们会自定义登出的URL以及成功登出后应该跳转到哪个URL,Spring Security也支持我们进行自定义。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 任何角色允许访问
                .antMatchers("/", "/index").permitAll()
                // 仅admin角色可以访问
                .antMatchers("/admin/**").hasRole("admin")
                // admin和manager两个角色可以访问
                .antMatchers("/manager/**").hasAnyRole("admin", "manager");

        // 没有权限进入内置的登录页面
        http.formLogin();
        // 自定义登出逻辑
        http.logout().logoutUrl("/myLogOut").logoutSuccessUrl("/index");
    }

当Post方式请求/myLogOut的时候就会触发Spring Security的登出逻辑,并且登出后会跳转到/index界面。

注意:在本案例中,是使用浏览器进行测试的,而且没有html的页面,所以使用浏览器发起post请求比较困难,那么使用get请求发起可以吗?默认是不行的,因为Spring Security默认开启了CSRF校验,所有改变状态的请求都必须以POST方式提交,为了能验证我们这个例子,我们需要把CSRF校验关掉,即在如上logout代码后面加上如下的配置:

// 暂时关闭CSRF校验,允许get请求登出
http.csrf().disable();

此时再重启应用,就可以验证localhost:8080/myLogOut的登出逻辑了。

六、记住我功能

当我们没有开启记住我功能的时候,登录root用户后,如果关掉浏览器,重新打开网址,会发现登录已经退出了,这是因为登录信息只在当前会话有效。

如果我们想要在某个时间段以内,一直使root用户处于登录状态,那么就需要在浏览器端设置一个cookie,在有效期内,这个cookie所属的用户就一直是登录的状态。同样的,只要在上面注销登录的代码后面加上:

// 开启remember me功能,有效期默认14天
http.rememberMe();

此时内置的登录页面会出现记住我的选择框,当我们选择上登录后,浏览器端就会有当前用户的cookie信息了(名称为remember-me),在它过期之前,登录状态就一直有效。

需要用户主动退出登录,也就是调用我们上面的/myLogOut才能将cookie清除并退出登录。

如果是自定义的登录页面,可以在后面链式调用rememberMeParameter()方法,传入自己的rememberme参数名称即可。

以上是关于Spring Security的基本使用方法,使用数据库及其它特性将会在后面的文章中予以说明。

七、会话管理

在以上例子中,认证和授权都是Spring Security自动进行的。但是有的时候我们需要管理会话,比如从会话中获取用户姓名、用户的权限信息;会话策略选择以及会话超时设置等。

我们只需要增加如下的方法即可:

    private String getName(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication.getPrincipal();
        if(principal == null){
            return "游客";
        }
        if(principal instanceof UserDetails){
            UserDetails userDetails = (UserDetails) principal;
            return userDetails.getUsername();
        } else{
            return principal.toString();
        }
    }

该方法使用SecurityContextHolder获取上下文信息,然后再获取到其中的用户名即可,当然其中还提供了可以获取密码、权限信息等方法。

Session的管理策略有以下几种:

  • always,如果没有Session就会创建一个;
  • ifRequired,登录时如果有需要,就创建一个;
  • never,不会主动创建session,如果其它地方创建了session,就会使用它;
  • stateless,不会创建也不会使用session;

其中ifRequired是默认的模式,stateless是采用token机制时,session禁用的模式,设置方法如下:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
    }

至于session的超时和安全可以在配置文件中设置:

# 超时时间设置
server.servlet.session.timeout=3600s
# 浏览器脚本将无法访问cookie
server.servlet.session.cookie.http‐only=true
# cookie将仅通过HTTPS连接发送
server.servlet.session.cookie.secure=true

到此这篇关于Spring Security入门demo案例的文章就介绍到这了,更多相关Spring Security入门内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring Security实现微信公众号网页授权功能

    微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用户的微信用户信息.如果用户在微信客户端中访问我们第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑.今天就结合Spring Security来实现一下微信公众号网页授权. 环境准备 在开始之前我们需要准备好微信网页开发的环境. 微信公众号服务号 请注意,一定是微信公众号

  • SpringSecurity数据库进行认证和授权的使用

    目录 一.准备工作 1.1 导入相关依赖 1.2 配置信息 1.3 数据库准备 1.4 实体类的创建 1.5 Dao层的创建 1.6 Service层的编写 1.7 Security配置 1.8 密码加密 1.9 测试结果 在前面的文章中,我们介绍了Spring Security基于内存的一些基本使用方法,但在真实的业务场景中,用户的账号.密码以及角色信息肯定都是存放在数据库中的,所以我们需要从数据库中来加载认证和授权的数据. 一.准备工作 如下案例是基于上一篇中的案例改造而来,所以建议先阅读前

  • SpringSecurity实现动态url拦截(基于rbac模型)

    目录 1.了解主要的过滤器 1.SecurityMetadataSource 2.UserDetailsService 3.AccessDecisionManager 2.正式实战了 1 使用idea的Srping Initializr 创建一个项目 我的版本如下Pom.xml 2,创建一个springSecurity配置类,你也可以使用配置文件的方法.我这里使用了boot的配置类 3.自定义SecurityMetadataSource拦截器 后续会讲解如何实现方法拦截.其实与url拦截大同小异

  • 带你详细了解Spring Security的注解方式开发

    目录 默认情况下,不会开启注解,如果想用注解,需要开启注解支持. 总结 默认情况下,不会开启注解,如果想用注解,需要开启注解支持. 在启动类上开启: @EnableGlobalMethodSecurity(securedEnabled = true) @SpringBootApplication @ComponentScan(basePackages = {"com.example"}) // 开启springSecurity注解支持 @EnableGlobalMethodSecuri

  • SpringSecurity怎样使用注解控制权限

    一般的系统在权限设计上,都会分为角色.权限(RDBC),复杂一点的可能会有用户组.组织之类的概念. 用户的权限是写死的,对应于后台的接口或者资源,是没办法改变的,一般不对用户开放修改权限. 管理员用户可以通过给角色分配权限的方式,来实现访问控制. 所以当我们写过滤器,或者用一些安全框架时(比如Shiro,Spring Security),也需要将可变的"角色",转化为不可变的"权限",注入到框架中. 具体的可以看我之前写的一篇(Spring Security整合jw

  • Spring Security入门demo案例

    目录 一.简介 二.入门案例 三.自定义认证逻辑 四.自定义授权逻辑 五.注销登录 六.记住我功能 七.会话管理 一.简介 Spring Security是一个高度自定义的安全框架.利用Spring IoC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作.主要包含如下几个重要的内容: 认证(Authentication),系统认为用户是否能登录. 授权(Authorization),系统判断用户是否有权限去做某些事情. 二.入门案例 首先引入必要的

  • Spring AOP入门Demo分享

    在阅读本文之前,大家可先行参阅<简单理解Spring之IOC和AOP及代码示例>一文,简单了解下ioc和aop的相关内容.下面进入正题. 本文将会一步一步创建一个最简单的例子,来使用Spring的AOP特性,算是一个Spring AOP的入门Demo.作为一个初学者,运行出这么简单的一个Demo也踩了很多的坑. OOP的问题,AOP的补充 当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代

  • 浅谈spring security入门

    一 介绍 本节给知识追寻者给大家带来的是springSecurity入门篇,主要是简述下springSecrurity的启动原理和简单的入门搭建: 二 核心模块介绍 spring-security-core : 包含核心身份验证和access-contol类和接口,远程支持和基本配置AP: spring-security-web: web , url登陆验证和访问控制: spring-security-config: 支持xml 或者java注解配置: 当然其模块远不止这些,比如CAS,ALC,

  • Spring Boot如何使用Spring Security进行安全控制

    我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache Shiro.spring Security). 本文将具体介绍在Spring Boot中如何使用Spring Security进行安全控制. 准备工作 首先,构建一个简单的Web工程,以用于后续添加安全控制,也可以用之前Chapter3-1-2做为基础工程.若对如何使用Spring Boot构建We

  • Spring Security十分钟入门教程

    目录 写在前面 目标 开始 不引入Spring Security访问接口 引入Spring Security访问接口 退出登录 后记 写在前面 我们在学习技术的过程中,学习的渠道大概有以下几种:看书,视频,博客.我们会发现,一种技术开始流行的时候,各种形式的讲述也就出现了.那么,出书,录视频,写博客的人,在他们之前,是没有什么现成的东西让他们学习的,他们是怎么上手的呢?换句话说,怎么才能有效的快速的上手一门技术呢? 这篇文章,我们一起从零开始学习SpringSecurity,技术点不重要,重要的

  • 手把手带你入门 Spring Security的具体流程

    Spring Security 是 Spring 家族中的一个安全管理框架,实际上,在 Spring Boot 出现之前,Spring Security 就已经发展了多年了,但是使用的并不多,安全管理这个领域,一直是 Shiro 的天下. 相对于 Shiro,在 SSM/SSH 中整合 Spring Security 都是比较麻烦的操作,所以,Spring Security 虽然功能比 Shiro 强大,但是使用反而没有 Shiro 多(Shiro 虽然功能没有 Spring Security

  • Spring Security 中如何让上级拥有下级的所有权限(案例分析)

    答案是能! 松哥之前写过类似的文章,但是主要是讲了用法,今天我们来看看原理! 本文基于当前 Spring Security 5.3.4 来分析,为什么要强调最新版呢?因为在在 5.0.11 版中,角色继承配置和现在不一样.旧版的方案我们现在不讨论了,直接来看当前最新版是怎么处理的. 1.角色继承案例 我们先来一个简单的权限案例. 创建一个 Spring Boot 项目,添加 Spring Security 依赖,并创建两个测试用户,如下: @Override protected void con

  • spring security在分布式项目下的配置方法(案例详解)

    分布式项目和传统项目的区别就是,分布式项目有多个服务,每一个服务仅仅只实现一套系统中一个或几个功能,所有的服务组合在一起才能实现系统的完整功能.这会产生一个问题,多个服务之间session不能共享,你在其中一个服务中登录了,登录信息保存在这个服务的session中,别的服务不知道啊,所以你访问别的服务还得在重新登录一次,对用户十分不友好.为了解决这个问题,于是就产生了单点登录: **jwt单点登录:**就是用户在登录服务登录成功后,登录服务会产生向前端响应一个token(令牌),以后用户再访问系

  • Spring Security 自动踢掉前一个登录用户的实现代码

    登录成功后,自动踢掉前一个登录用户,松哥第一次见到这个功能,就是在扣扣里边见到的,当时觉得挺好玩的. 自己做开发后,也遇到过一模一样的需求,正好最近的 Spring Security 系列正在连载,就结合 Spring Security 来和大家聊一聊这个功能如何实现. 本文是本系列的第十三篇,阅读前面文章有助于更好的理解本文: 挖一个大坑,Spring Security 开搞! 松哥手把手带你入门 Spring Security,别再问密码怎么解密了 手把手教你定制 Spring Securi

  • Spring Security 在 Spring Boot 中的使用详解【集中式】

    1.1 准备 1.1.1 创建 Spring Boot 项目   创建好一个空的 Spring Boot 项目之后,写一个 controller 验证此时是可以直接访问到该控制器的. 1.1.2 引入 Spring Security   在 Spring Boot 中引入 Spring Security 是相当简单的,可以在用脚手架创建项目的时候勾选,也可以创建完毕后在 pom 文件中加入相关依赖. <dependency> <groupId>org.springframework

随机推荐