SpringSecurity学习笔记

一 .项目启动

在项目中若添加SpringSecurity的依赖

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

启动项目时会默认拦截所有的请求,要求必须登录之后才能进行相应的访问
在这里插入图片描述

二.SpringSecurity本质是一个过滤链

1.FilterSecurityInterceptor最底端过滤器是一个方法级的过滤器
2.ExcpetionTranslationFilter:是个异常过滤器,用来处理认证需求出现的异常
3.UsernamePassAuthenticationFilter:对/login的Post请求做拦截,校验表单中的用户名,密码。

三.两个重要的接口

UseDetailService 查询数据库用户名密码
PasswordEncoding数据加密,用于返回User对象中的密码加密

四.web权限方案

1.设置登录的用户名和密码通过配置文件
在这里插入图片描述
通过配置类自定义用户名密码,首先创建配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }
	@Bean
    public PasswordEncoder password() {
        return new BCryptPasswordEncoder() ;
    }
}

创建MyUserdetaiService 实现UserService接口

@Service("userDetailsService")
public class MyUserDetailService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        return new User("ming", new BCryptPasswordEncoder().encode("123"), AuthorityUtils.commaSeparatedStringToAuthorityList("role"));
    }

}

五.自定义登录界面

载配置类中进行相关的实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/user/login" method="post">
        用户名 : <input type="text" name="username"><br>
        密码: <input type="password" name="password"><br>
        <input type="submit" value="login">
    </form>
</body>
</html>

在配置类中添加


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //自定义登录界面
        http.formLogin().loginPage("/login.html") //登录页面设置
        .loginProcessingUrl("/user/login") //登录提交到哪个controller
        .defaultSuccessUrl("/index").permitAll() //登录成功后跳转的路径
        .and().authorizeRequests().antMatchers("/","/hello","/user/login").permitAll()//设置哪些路径可以直接访问不需要认证
        .anyRequest().authenticated() //所有请求都需要认证
        .and().csrf().disable(); //关闭csrf防护模式

    }
@RestController
public class LoginController {
    @RequestMapping("/hello")
    public String login(){
        return "hello security";
    }
    @GetMapping("/index")
    public String index(){
        return "hello index";
    }

}


1.hasAuthority的配置

首先在SpringSecurity配置类中加入 .antMatchers("/index").hasAuthority("admins")
然后在MyUserDetailService中加入 AuthorityUtils.commaSeparatedStringToAuthorityList("admin")
此时会报 There was an unexpected error (type=Forbidden, status=403).因为该用户没有admins的权限 将admin改为admins就可以访问了

2.hasAnyAuthority 针对多个用户

antMatchers("/index").hasAnyAuthority("admins,manager") 该用户只要有任何一个权限就可以访问

3.hasRole

   .antMatchers("/index").hasRole("sale")
   AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale"));

此时注意用户权限中要加入"ROLE"
在源码中可以看到

private static String hasRole(String role) {
		Assert.notNull(role, "role cannot be null");
		if (role.startsWith("ROLE_")) {
			throw new IllegalArgumentException(
					"role should not start with 'ROLE_' since it is automatically inserted. Got '"
							+ role + "'");
		}
		return "hasRole('ROLE_" + role + "')";
	}

4.hasAnyRole表示角色用于任何一权限都可以

六.自定义403界面

   //自定义403界面
        http.exceptionHandling().accessDeniedPage("/unsuccessful.html");

七.SpringSecurity认证和授权

1.Secured
首先要在启动类或配置类中加入 @EnableGlobalMethodSecurity(securedEnabled = true)注解
然后在Controller类中加入 @GetMapping("/update")
    @Secured({"ROLE_sale","ROLE_manager"})
    public String update(){
        return "hello update";
    }
 2. PreAuthorize在方法执行前认证(需要开启@EnableGlobalMethodSecurity(prePostEnabled = true)@GetMapping("/update2")
    @PreAuthorize("hasAuthority('admins')")
    public String update2(){
        return "hello update";
    }
    3.在方法执行后认证
    2. PostAuthorize在方法执行后认证(需要开启@EnableGlobalMethodSecurity(prePostEnabled = true)@GetMapping("/update3")
    @PostAuthorize("hasAuthority('admin')")
    public String update3(){
        System.out.println("正常访问");
        return "hello update";
    }
    4.@PostFilter("filterObject.username=="admin")对方法返回值进行过滤
    5.@PreFileter	对参数进行过滤

在这里插入图片描述

对admin2进行了过滤只输出了admin1

在这里插入图片描述

八.自定义退出界面

```java
  //自定义退出界面
        http.logout().logoutUrl("/logout").logoutSuccessUrl("hello").permitAll();``

九自动登录

在这里插入图片描述
在这里插入图片描述
首先创建数据库表

CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

修改配置类


package com.cp.springsecurity.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;

import javax.sql.DataSource;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    //注入数据源
    @Autowired
    private DataSource dataSource;
    @Bean
    public PersistentTokenRepository psistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return  jdbcTokenRepository;
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }
    @Bean
    public PasswordEncoder password() {
        return new BCryptPasswordEncoder() ;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //自定义403界面
        http.exceptionHandling().accessDeniedPage("/unsuccessful.html");
        //自定义退出界面
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/hello").permitAll();
        //自定义登录界面
        http.formLogin().loginPage("/login.html") //登录页面设置
        .loginProcessingUrl("/user/login") //登录提交到哪个controller
        .defaultSuccessUrl("/index").permitAll() //登录成功后跳转的路径
        .and().authorizeRequests().antMatchers("/","/hello","/user/login").permitAll()//设置哪些路径可以直接访问不需要认证
                //表示当前登录只有具有admins权限才可以访问这个路径
               // .antMatchers("/index").hasAuthority("admins")
                //.antMatchers("/index").hasAnyAuthority("admins,manager")
                .antMatchers("/index").hasRole("sales")
        .anyRequest().authenticated() //所有请求都需要认证
        .and() .rememberMe().tokenRepository(psistentTokenRepository())
                .tokenValiditySeconds(60)//设置有效市场60秒
                .userDetailsService(userDetailsService)
        .and().csrf().disable();//关闭csrf防护模式
    }
}

结束语

本文是根据B站up主尚硅谷分享的视频,进行学习整理他的视频链接为
https://www.bilibili.com/video/BV15a411A7kP?p=40

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值