Spring Security(Springboot-v2.5.5)

概述

SpringSecurity是基于Spring的安全框架,作用和shiro一样,用于认证授权

SpringSecurity和shiro对比

  1. SpringSecurity

和Spring无缝结合
全面的权限控制
专门为Web开发而设计(旧版本不能脱离Web环境,新版本对整个框架进行了分层抽取,分成了核心模块和Web模块,单独引入核心模块就可以脱离Web环境)
重量级

  1. shiro

轻量级,shiro主张的理念是把复杂的事情变简单。针对性能又更高要求的互联网应用又更好表现
通用性(不局限于Web环境)
在Web环境下特定的需求(如特定的认证方式),需要手动编写代码定制,代码量大

  1. 在SSM中整合SpringSecurity相对于shiro来说更加麻烦,shiro虽然功能没有spring强大但在许多场景也够用了,而springboot提供的自动化配置方案省去了spring security的大量配置;所以一般常见的安全管理技术栈是SSM+Shiro;SpringBoot+SpringSecurity

入门案例

  1. 引入依赖spring-boot-starter-security
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 编写controller进行测试
@RestController
@RequestMapping("security")
public class HelloWorld {

    @GetMapping("test1")
    public String test1(){
        return "hello security!!";
    }
}

运行起来后,在控制台会有密码的输出,访问该controller会跳转到login页面,账号默认为user
在这里插入图片描述

基本原理

SpringSecurity本质是一个过滤器链,每个过滤器都实现对应的功能,3个重要过滤器:

  1. FilterSecurityInterceptor:一个方法级的权限过滤器,基本位于过滤器链的最底层
  2. ExceptionTranslationFilter:异常过滤器,用于处理在认证授权过程中抛出的异常
  3. UsernamePasswordAuthenticationFilter:对/login的POST请求进行拦截,校验表单中的用户名和密码

过滤器的加载流程

  1. 用户通过SpringSecurity配置过滤器DelegatingFilterProxy(SpringBoot自动配置了),该过滤器的doFilter方法调用了自身的initDelegating方法,在initDelegating方法中加载了FilterChainProxy的bean
  2. FilterChainProxydoFilter方法调用了自身的doFilterInternal方法,通过迭代器将所有需要加载的过滤器加载到过滤器链中

自定义开发的两个重要接口

UserDetailsService

当什么也没有配置的时候,账号和密码都是由SringSecurity自动生成的。而在实际项目中账号和密码都是从数据库查来的,所以要自定义认证逻辑;查询数据库得到用户名和密码就由UserDetailsService接口来实现,类似Shiro中的Realm

实现流程

  1. 创建类集成UsernamePasswordAuthenticationFilter,重写三个方法
  2. 创建类实现UserDetailsService编写查询数据过程,返回User(UserDetails接口的实现)对象,这个User对象是Security提供的对象(包含用户名、密码、权限,以及用户状态)

PasswordEncoder

存储在数据库的密码不会是用户注册时输入的原始密码,而是加密过的;在认证的时候就需要对用户登录时输入的原始密码进行加密,该操作就由PasswordEncoder实现;security在对加密的密码进行认证时会去找用户配置的PasswordEncoder的实现
这个接口用于密码存储的加密,有三个方法:

  1. String encode(CharSequence rawPassword);:用于对前端接收到的密码进行编码
  2. boolean matches(CharSequence rawPassword, String encodedPassword);:将经过编码的密码和数据库查到的密码进行匹配
  3. default boolean upgradeEncoding(String encodedPassword) {return false;}:为了安全,如果需要重复编码提高安全性则返回true,默认实现返回false

SpringSecurity认证

设置登录的用户名和密码

  1. 通过配置文件
spring:
  security:
    user:
      name: laowa
      password: 123456
  1. 通过配置类,继承自WebSercurityConfigurerAdapter方法,重写它的configure方法
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //对密码进行加密
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = encoder.encode("123456");
        auth.inMemoryAuthentication().withUser("laowa").password(password);
    }

    /**
     * 配置对应加密方式的编码对象
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
  1. 自定义编写实现类实现UserDetailsService接口
@Service
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		//开发中这里进行数据库的访问
        return new User("laowa3",new BCryptPasswordEncoder().encode("123456"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("role"));
    }
}

自定义登录页面

  1. 在配置类中重写cofigure(HttpSecurity http)方法
@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                //自定义登录页面
                .loginPage("/static/login.html")
                //定义登录请求的路径
                .loginProcessingUrl("/user/login")
                //定义默认登陆成功后跳转的路径(在用户登录时有效,如果用户访问请求被拦截到登录页面则会跳转到用户访问的请求),permitAll表示任何用户都有权限
                .defaultSuccessUrl("security/test1").permitAll()
                //不需要认证就能访问的页面
                .and().authorizeRequests().antMatchers("/","/security/test2","user/login").permitAll()
                //所有请求都可以访问
                .anyRequest().authenticated()
                //关闭csrf防护
                .and().csrf().disable();
    }

用户注销

//设置注销路径和注销成功后跳转的路径
http.logout().logoutUrl("/logout")
                .logoutSuccessUrl("/security/test2").permitAll();

自动登录功能

实现原理

在这里插入图片描述

操作步骤

  1. 创建数据库表,也可以让框架来创建,建表语句在JdbcTokenRepositoryImpl类中
create table persistent_logins (
username varchar(64) not null, 
series varchar(64) primary key,
token varchar(64) not null, 
last_used timestamp not null);
  1. 配置类中注入数据源,配置数据库操作对象
	@Autowired
    private DataSource dataSource;

    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //是否在启动时自动创建表
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
  1. 开启自动登录
//添加自动登录的处理
http.and().rememberMe().tokenRepository(persistentTokenRepository())
    //设置token有效时间
    .tokenValiditySeconds(60)
    //设置登录的业务逻辑类
    .userDetailsService(userDetailsService)
  1. 前端页面登录表单添加复选框,name为remember-me

SpringSecurity授权

控制访问

  1. hasAuthority:如果当前主体具有**参数指定的权限(一个参数)**则返回true,否则返回false
  2. hasAnyAuthority:如果当前主体有任何提供的权限(多个权限参数,满足一个即可),给定的作为一个逗号分隔的字符串列表的化,返回true
  3. hasRole:如果当前主体具有参数指定的一个角色(为主体添加角色需要加前缀ROLE_)
  4. hasAnyRole:如果当前主体具有参数列表中的任意一个角色

自定义403

  1. 页面
//没有权限跳转到该页面
http.exceptionHandling().accessDeniedPage("403.html");
  1. 处理器
//实现接口AccessDeniedHandler,处理ajax请求
http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

常用注解

  1. @EnableGlobalMethodSecurity(securedEnabled=true):用于启动类或配置类上,表示启用security的其他注解
  2. @Secured:用于controller的处理器方法上,参数value为角色集(注意需要加ROLE_前缀);表示这个资源只有拥有设置的角色的用户才能访问
  3. @PreAuthorize在用户进入方法前进行权限的校验,参数可以为http判断权限和角色的四个方法的字符串hasRole、hasAnyRole、hasAuthor、hasAnyAuthor
  4. @PostAuthorize在方法执行之后进行权限的校验,与@PreAuthorize类似
  5. @PostFilter:对处理器方法的返回值及逆行过滤
  6. @PreFilter:对处理器方法的传入参数进行过滤

底层原理

认证流程

  1. UsernameAuthentationFilter调用父类AbstractAuthenticationProcessingFilter的doFilter方法
    在这里插入图片描述

  2. 父类调用子类方法attemptAuthentication进行认证的过程
    在这里插入图片描述

  3. 用户名和密码构建UsernamePasswordAuthenticationToken对象的过程
    在这里插入图片描述

  4. this.getAuthenticationManager().authenticate(authRequest);认证过程(父接口AuthenticationManager调用子类ProviderManager实现的authenticate方法)
    在这里插入图片描述

授权流程

权限访问的流程主要由ExceptionTranslationFilterFilterSecurityInterceptor两个过滤器完成

  1. ExceptionTranslationFilter
    在这里插入图片描述
  2. FilterSecurityInterceptor
    在这里插入图片描述
    在这里插入图片描述

认证信息与session的绑定

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
layui-v2.5.5是一款基于layui框架开发的织梦后台管理自适应模板。织梦是一种使用PHP语言开发的内容管理系统,通过此模板可以方便地对织梦后台进行管理。 这个模板的主要特点是自适应布局设计,可以自动根据不同的设备屏幕大小进行调整,实现了在PC端、平板电脑和手机端的兼容性。不同设备上显示的页面布局会自动适应屏幕,使得用户可以在不同设备上方便地访问和操作织梦后台。 此模板还具备丰富的功能和界面设计,包括常用的用户管理、栏目管理、内容管理、扩展功能等。用户管理功能包括对用户的增删改查,可以方便地管理后台用户权限。栏目管理功能可以对网站的栏目进行设置和管理,包括栏目的增删改查等操作。内容管理功能可以对网站的内容进行管理,包括文章的发布、编辑和删除等操作。同时,模板还提供了强大的扩展功能,可以根据具体需求进行自定义功能的添加和开发。 此外,layui-v2.5.5织梦后台管理自适应模板还具备良好的用户体验,界面简洁美观,操作简单直观。用户可以通过点击、拖拽等方式进行操作,大大提高了用户的使用效率和便利性。 总的来说,layui-v2.5.5织梦后台管理自适应模板是一款功能全面、界面美观、易于使用的织梦后台管理模板,能够满足用户对织梦后台管理的各项需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值