十分钟带你入门SpringSecurity_怎么学springsecurity(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

在这里插入图片描述

UsernamePasswordAuthenticationFilter:对/loginPOST请求做拦截,校验表单中用户名、密码

在这里插入图片描述

③ 过滤器如何进行加载的?
  • 使用SpringSecurity配置过滤链器
    • DelegatingFilterProxy

通过getBean()获取过滤器的名称FilterChainProxy

在这里插入图片描述

将现有的过滤器通过this.getFilters()添加到List<Filter>的过滤链中去

在这里插入图片描述
在这里插入图片描述

④ UserDetailsService接口

当什么也没有配置的时候,账号和密码是由SpringSecurity定义生成的,而在实际的项目中账号和密码都是从数据库中查询出来的。所以要通过自定义逻辑控制认证逻辑。

需要自定义逻辑时,只需要实现UeserDetailsService接口即可!
在这里插入图片描述

返回值:UserDetails

这个类是系统默认的用户主体

public interface UserDetails extends Serializable {

	/\*\*
 \* 返回授予用户的权限,无法返回null
 \*/
	Collection<? extends GrantedAuthority> getAuthorities();

	/\*\*
 \* 返回用于验证用户的密码
 \*/
	String getPassword();

	/\*\*
 \* 返回用于验证用户的用户名,没有返回null
 \*/
	String getUsername();

	/\*\*
 \* 表示判断账户是否过期
 \*/
	boolean isAccountNonExpired();

	/\*\*
 \* 表示判断账户是否被锁定
 \*/
	boolean isAccountNonLocked();

	/\*\*
 \* 表示凭证{密码}是否过期
 \*/
	boolean isCredentialsNonExpired();

	/\*\*
 \* 表示当前用户是否可用
 \*/
	boolean isEnabled();

}

以下是UserDetails的实现类

在这里插入图片描述

以后我们只需要使用User这个实体类即可!

在这里插入图片描述

  • 方法参数:username

表示用户名。此值是客户端表单传递过来的数据,默认情况下必须叫username,否则无法接收!

⑤ PasswordEncoder接口
//表示把参数按照特定的解析规则进行解析
String encode(CharSequence rawPassword);
/\*\*
 表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配,如果密码匹配,则返回true,如果不匹配,则返回 false,第一个参数表示需要被解析的密码,第二个参数表示存储的密码
\*/
boolean matches(CharSequence rawPassword,String encodedPassword);
//表示如果解析密码能够再次进行解析,且达到更安全的结果则返回 true,否则返回false,默认返回false
default boolean upgradeEncoding(String encodedPassword){
	return false;
}

在这里插入图片描述

BCryptPasswordEncoderSpring Security官方推荐的密码解析器,平时多使用这个解析器。

BCryptPasswordEncoder是对bcrypt强散列方法的具体实现。是基于Hash算法实现的单向加密,可以通过strength控制加密强度,默认为10

测试

@Test
public void testBCrypt(){
  // 创建密码解析器
  BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
  // 对密码进行加密
  String password = passwordEncoder.encode("admin");
  System.out.println("加密之后的密码:"+password);

  //判断原始密码与加密后的密码是否一致
  boolean isTrue = passwordEncoder.matches("admin", password);
  System.out.println("密码是否相等:"+isTrue);
}

2.6 SpringBoot对 Security的自动配置
 https://docs.spring.io/springsecurity/site/docs/5.3.4.RELEASE/reference/html5/#servlet-hello

🌽  SpringSecurity Web权限方案
① 设置登录的用户名和密码
  • 方式一:配置文件
spring.security.user.name=admin
spring.security.user.password=admin

  • 方式二:配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123");
        auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
    }
}

  • 方式三:自定义编写实现类

第一步 创建配置类,设置使用哪个userDetailsService实现类

在这里插入图片描述

第二步:编写实现类,返回User对象,User对象有用户名密码和操作权限

在这里插入图片描述

② 自定义设置登录页面不需要认证可以访问
  • 在配置类实现相关的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()//自定义自己编写的登录页面
            .loginPage("/login.html")//登录页面设置
            //填写完用户名和密码之后需要提交表单操作到指定的Controller中
            .loginProcessingUrl("/user/login")//登录访问路径
            .defaultSuccessUrl("/index").permitAll()//默认登录成功,跳转到的路径
            .and().authorizeRequests()//定义哪些url需要认证,哪些不需要认证
            .antMatchers("/","/index","/user/login").permitAll()//设置哪些路径可以直接访问,不需要认证
            .anyRequest().authenticated()//所有请求都需要认证
            .and().csrf().disable();//关闭csrf防护
    }

③ 基于角色或权限进行访问控制
(1) hasAuthority方法

如果当前的主体具有指定的权限,则返回true,否则返回false

  • 修改配置类

在这里插入图片描述

  • 修改MyUserDetailsService手动给登录用户添加所属权限
    在这里插入图片描述

    • 权限为admins

在这里插入图片描述

  • 权限为其他时:

在这里插入图片描述

(2) hasAnyAuthority方法

如果当前的主体有任何提供的角色(给定的作为一个逗号分隔的字符串列表)的话,返回true

在这里插入图片描述

(3) hasRole方法

如果用户具备给定的角色就允许访问,否则出现403

如果当前主体具有指定的角色,则返回true

底层源码

	private static String hasRole(String role) {
		Assert.notNull(role, "role cannot be null");
		Assert.isTrue(!role.startsWith("ROLE\_"),
				() -> "role should not start with 'ROLE\_' since it is automatically inserted. Got '" + role + "'");
		return "hasRole('ROLE\_" + role + "')";
	}

在这里插入图片描述

注意:由于底层对角色信息进行了甄别,判断角色是否以ROLE_开头,如果不是则自动拼接,所以在测试的时候需要添加ROLE_

在这里插入图片描述

(4) hasAnyRole

表示用户具备任何一个条件都可以访问。

给用户添加角色:

修改配置类

在这里插入图片描述

④ 自定义403没有权限访问页面

在这里插入图片描述

在配置类中进行配置

在这里插入图片描述

⑤ 注解使用
(1) @Secured

判断是否具有角色,另外注意的是这里匹配的字符串需要添加前缀ROLE_

使用之前需要先开启注解功能!

@EnableGlobalMethodSecurity(securedEnabled = true)

@EnableGlobalMethodSecurity(securedEnabled = true)
@SpringBootApplication
@MapperScan("com.pdx.mapper")
public class SpringSecurity03Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecurity03Application.class, args);
    }

}

编写前端控制器使用注解,设置角色

@GetMapping("/update")
@Secured({"ROLE\_sale","ROLE\_manager"})
@ResponseBody
public String update(){
  return "hello update";
}

userDetailsService设置用户角色

在这里插入图片描述

(2) @PreAuthorize

先开启注解功能:

@EnableGlobalMethodSecurity(prePostEnabled = true)

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

@PreAuthorize:注解适合进入方法前的权限验证,@PreAuthorize可以将登录用户的roles/permissions参数传到方法中。

在controller的方法上添加注解
在这里插入图片描述

(3) @PostAuthorize

先开启注解功能

@EnableGlobalMethodSecurity(prePostEnabled = true)

@PostAuthorize注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值的权限

在controller的方法上添加注解

在这里插入图片描述

如果使用一个没有权限访问此资源的用户去访问此资源的时候肯定是要跳转到之前我们自定义403页面的,但是实际上此方法已经执行过了!
在这里插入图片描述

(4) @PostFilter【少用】

@PostFilter:权限验证之后对数据进行过滤,留下用户名是admin1的数据

表达式中的filterObject引用的是方法返回值List中的某一个元素

@GetMapping("/getAll")
@PostAuthorize("hasAnyAuthority('admins')")
@PostFilter("filterObject.username == 'admin1'")
public List<Users> getAllUsers(){
  List<Users> list = new ArrayList<>();
  list.add(new Users(11,"admin1","666"));
  list.add(new Users(21,"admin2","888"));
  System.out.println(list );
  return list;
}

(5) @PreFilter【少用】

@PreFilter:进入控制器之前对数据进行过滤

@GetMapping("/putAll")
@PreAuthorize("hasAnyAuthority('admins')")
@PreFilter(value = "filterObject.id%2==0")
public List<Users> putAll(@RequestBody List<Users> list){
  list.forEach(t ->{
    System.out.println(t.getId()+"\t"+t.getUsername());
  });
  return list;
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Filter`:进入控制器之前对数据进行过滤

@GetMapping("/putAll")
@PreAuthorize("hasAnyAuthority('admins')")
@PreFilter(value = "filterObject.id%2==0")
public List<Users> putAll(@RequestBody List<Users> list){
  list.forEach(t ->{
    System.out.println(t.getId()+"\t"+t.getUsername());
  });
  return list;
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
[外链图片转存中…(img-C03Q2hai-1713382059634)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值