springSecurity笔记


视频地址

https://www.bilibili.com/video/BV15a411A7kP?from=search&seid=9400151469496223964

资料地址

链接:https://pan.baidu.com/s/18NAnL40uxvmpPuLZXKM7uA 提取码:t209

入门测试


  1. 配置pom.xml文件
	<parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.3.4.RELEASE</version>
    </parent>

    <dependencies>
        <!-- web场景 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring的安全框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>


  1. 写主启动类
@SpringBootApplication
public class SpringSecurityMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityMainApplication.class,args);
    }
}
  1. 配置application.porperties文件 配置文件
# 设置端口为8080
server.port=8080

  1. 写controller
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("hello")
    public String hello(){
        return "hello Security";
    }	
}

直接run主启动类,访问 test/hello

在这里插入图片描述
页面跳转
在这里插入图片描述
用户名:user 密码
在这里插入图片描述

登录后:
在这里插入图片描述



设置用户名密码

在这里插入图片描述

方法一:通过配置文件

spring.security.user.name=atguigu
spring.security.user.password=atguigu


方法二:通过配置类

在这里插入图片描述
创建SecurityConfig配置类

package com.atguigu.config;

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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123");
        //将123 给加密了,下面的方法,是将  加密后的密码给解密为   123 跟  输入的密码进行匹配!!!

        //role角色必须要写!!!
        // 密码必须进行加密后,再进行传递进去,才行。
        auth.inMemoryAuthentication().withUser("atguigu").password(password).roles("admin");
    }

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

}

输入: atguigu 123 就可


方式三:自定义编写实现类(连接数据库使用)

先出配置文件中找用户名密码,没有从配置类中找,再没有就从这个自定义类中找,没有就默认的用户名密码

在这里插入图片描述

第一步:创建配置类。设置是使用哪个userDetaillsService实现类

注意:放在一个配置类中写即可。
在这里插入图片描述

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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired  // 这个是一个接口,注入的是它的实现类
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 对应的实现类,使用BCryptPasswordEncoder 这个类进行加密的
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

    }

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

}

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

在这里插入图片描述

package com.atguigu.service;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userDetailsService")
public class MyUserDetailService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        //将用户对应的角色,封装为一个list集合,这里是使用了这个工具类
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        // 必须将密码加密后,才能进行放入
        return new User("mary",new BCryptPasswordEncoder().encode("123"),auths);
    }
}

输入: mary123 就可



案例:查询数据库完成认证

在这里插入图片描述

第一步:引入相关依赖

<!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--lombok 用来简化实体类-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

第二步:创建数据库和数据库表

Users表

create table users(
	 id bigint primary key auto_increment,
	username varchar(20) unique not null,
	password varchar(100)
);

在这里插入图片描述


第三步:创建对应的实体类

在这里插入图片描述

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Users {
    private Integer id;
    private String username;
    private String password;
}


第四步:整合mp,创建接口,继承mp接口

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

@Repository
public interface UsersMapper extends BaseMapper<Users> {
}


第五步:在MyUserDetailService调用mapper里面的方法查询数据库进行用户认证

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


package com.atguigu.service;

import com.atguigu.entity.Users;
import com.atguigu.mapper.UsersMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userDetailsService")
public class MyUserDetailService implements UserDetailsService {

    @Autowired
    UsersMapper usersMapper;	//注意这里

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //这里的username指的是表单传过来的用户名的值

        //调用userMapper方法,根据用户名查询数据库
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        //where usernanme = ?
        wrapper.eq("username",username);
        Users users = usersMapper.selectOne(wrapper);
        //判断
        if(users == null){
            throw new UsernameNotFoundException("用户名不存在");
        }

        //将用户对应的角色,封装为一个list集合,这里是使用了这个工具类
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");// 没有设置用户的角色的
        // 必须将密码加密后,才能进行放入
        return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
    }
}


第六步:在启动类添加MapperScan

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


第七步:连接数据库


# 设置端口为8080
server.port=8080

# 连接数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

run 成功 lucy 123



自定义用户登录页面(不需要认证也可以访问的页面)


1. 在配置类中实现相关配置

在这里插入图片描述

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired  // 这个是一个接口,注入的是它的实现类
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 对应的实现类,使用BCryptPasswordEncoder 这个类进行加密的
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

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




	//是这个配置 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //自定义自己编写的登录页面
        http.formLogin()
            .loginPage("/login.html")       //登录页面的设置
            .loginProcessingUrl("/user/login")           //登录访问路径,表单提交的地方,比如某个controller,但是逻辑是springSecurity自己实现
            .defaultSuccessUrl("/test/index").permitAll()    //登录成功之后,跳转的路径
            .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll()   //设置哪些路径可以直接访问,不需要认证
            .anyRequest().authenticated()
            .and().csrf().disable();    //关闭csrf防护 , 默认开启的,这个条件是可以忽略的,需要开启

    }
}

参考: 用不来,建议查看官网
在这里插入图片描述


2. 创建相关页面,controller

login.html
在这里插入图片描述

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

这里必须为参数名:username , password 底层代码写的, 必须为post


添加controller
在这里插入图片描述

访问:

/test/hello 已经不需要认证,可以直接访问
访问/test/index 会跳转到登录页面,登录成功后,才能访问

登录页面也是直接设置的页面


基于角色或限权进行访问控制

比如:某个页面,必须是管理员才能进行访问

1. hasAuthority 方法

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

修改配置类

在这里插入图片描述
对应cotroller
在这里插入图片描述
设置权限
在这里插入图片描述

访问即可。

  1. 除了不需要登录认证,能直接访问的页面,其他的页面都需要登录后,才能进行访问
  2. 在登录认证后的,某些网页是需要进行的角色才能进行访问的。
  3. 访问了没有权限的网页,会显示403。


2. hasAnyAuthority 方法

该用户的角色是 可以访问该网页角色中的一种,就可以访问。

修改配置类
在这里插入图片描述

用户角色
在这里插入图片描述

访问

登录后,访问/test/find 可以 , /test/findAll 不行 403页面



3. hasRole和hasAnyRole 方法

同理

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

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

在这里插入图片描述

修改角色
在这里插入图片描述
在这里插入图片描述

访问

在这里插入图片描述

用户角色
在这里插入图片描述

登录后,
在这里插入图片描述
在这里插入图片描述



自定义403页面


1. 修改配置类:

在这里插入图片描述

http.exceptionHandling().accessDeniedPage("/unauth");

在这里插入图片描述


2. 添加对应控制器或者是页面


@GetMapping("/unauth")
public String accessDenyPage(){
return "unauth";
}

unauth.html

<body>
<h1>对不起,您没有访问权限!</h1>
</body>

访问没有权限的网页就会出现该页面
在这里插入图片描述



注解使用


1. @Secured

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

用户有该限权是可以直接访问对应的controller的

在这里插入图片描述

@SpringBootApplication
@MapperScan("com.atguigu.mapper")
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SpringSecurityMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityMainApplication.class,args);
    }
}


在这里插入图片描述

@GetMapping("secured")
@Secured("ROLE_role")
public String helloUser(){
	return "hello,user";
}

在这里插入图片描述

2. @PreAuthorize 和 @PostAuthorize

PreAuthorize 先认证权限,通过后再执行方法 ,
PostAuthorize 先执行方法 , 后认证权限

在这里插入图片描述

    //测试限权,先验证
    @GetMapping("preAuthorize")
    @PreAuthorize("hasAnyAuthority('menu:system')")
    public String preAuthorize(){
        System.out.println("preAuthorize");
        return "preAuthorize";
    }

    //后验证
    @GetMapping("postAuthorize")
    @PreAuthorize("hasAnyAuthority('menu:system')")
    public String postAuthorize(){
        System.out.println("postAuthorize");
        return "postAuthorize";
    }

在这里插入图片描述

3. @PostFilter 不常用

@PostFilter :权限验证之后对数据进行过滤 留下用户名是 admin1 的数据
表达式中的 filterObject 引用的是方法返回值 List 中的某一个元素

在这里插入图片描述


4. @PreFilter 不常用

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

在这里插入图片描述



用户注销 / 退出

在这里插入图片描述



基于数据库的记住我(rember me)


1. 创建表

可以自动的创建,不用手动创建的

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;

2. 添加数据库的配置文件



# 设置端口为8080
server.port=8080

# 连接数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root


3. 编写配置类

@Configuration
public class BrowserSecurityConfig {

	@Autowired
	private DataSource dataSource;
	
	@Bean
	public PersistentTokenRepository persistentTokenRepository(){
		 JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
		 // 赋值数据源
		 jdbcTokenRepository.setDataSource(dataSource);
		 // 自动创建表,第一次执行会创建,以后要执行就要删除掉!
		 jdbcTokenRepository.setCreateTableOnStartup(true);	//手动创建设置为 false即可!!!
		 return jdbcTokenRepository;
	 }
}



4. 修改安全配置类

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.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired  // 这个是一个接口,注入的是它的实现类
    private UserDetailsService userDetailsService;

    @Autowired
    private PersistentTokenRepository tokenRepository;  //操作jdbc的那个对象

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 对应的实现类,使用BCryptPasswordEncoder 这个类进行加密的
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //开启记住我功能
        http.rememberMe()
                .tokenValiditySeconds(400)  //设置为400s
                .tokenRepository(tokenRepository)
                .userDetailsService(userDetailsService);


        //设置403页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");

        //自定义自己编写的登录页面
        http.formLogin()
            .loginPage("/login.html")       //登录页面的设置
            .loginProcessingUrl("/user/login")           //登录访问路径,表单提交的地方,比如某个controller,但是逻辑是springSecurity自己实现
            .defaultSuccessUrl("/success.html").permitAll()    //登录成功之后,跳转的路径,这个好像没有进行跳转

            .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll()   //设置哪些路径可以直接访问,不需要认证
                .antMatchers("/test/find").hasAuthority("role")
                .antMatchers("/test/findAll").hasAuthority("admin")
            .anyRequest().authenticated()
            .and().csrf().disable();    //关闭csrf防护 , 默认开启的,这个条件是可以忽略的,需要开启


        //退出
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();

    }
}

5. 页面添加记住我复选框

login.html文件

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

在这里插入图片描述

run 运行, 点击 记住我这个复选框后,将浏览器关闭后,在进行直接访问,是可以直接访问的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值