首页 > 编程语言 > 其他编程

Spring-Security

admin 其他编程 2021-05-25 09:20:09 spring security 
后台-系统设置-扩展变量-手机广告位-内容正文底部

概述

  1. 认证(你是谁,户/设备/系统
  2. 验证(你能干什么,也叫权限控制/授权,允许执行的操作)
  3. 基于Filter , Servlet, AOP实现身份认证和权限验证

实例驱动学习

入门案例

1、新建工程,导入依赖

<!--spring-security相关依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、配置访问地址,启动测试,获得秘钥

登陆名:user

密码:查看日志

获得秘钥

3、小结

使用AOP做了拦截,拦截后再访问的servlet

security相关配置

自定义用户名和密码

在Application.yml 中配置文件上的security的user和password

spring:
  security:
    user:
      name: admin
      password: admin

关闭验证

在启动类的注解中,排除安全验证,使用内存中的用户信息

关闭验证

使用内存中的账户

使用类WebSecurityConfigurerAdapter控制安全管理内容

1. 自定义类继承WebSecurityConfigurerAdapter,声明是个配置类、开启WebSecurity
2. 重写configure方法
3. 在SpringSecurity_v5.0版本中,密码必须使用一个加密方式
4. 构建一个方法创建一个BCrypt加密类,用于加密操作(BCrypt跨平台)
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
				// 得到一个加密类,
        PasswordEncoder passwordEncoder = passwordEncoder();
        auth.inMemoryAuthentication().withUser("zhangsan").password(passwordEncoder.encode("zhangsan")).roles();
        auth.inMemoryAuthentication().withUser("lisi").password(passwordEncoder.encode("lisi")).roles();
        auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("admin")).roles();
    }
		// 构建一个方法创建一个加密类,放入容器中
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

使用数据库的账户

1、导入依赖

<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>
<!--spring-jpa依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.4.5</version>
</dependency>

2、封装对象,创建一个实体类,初始化数据 使用JPA连接数据库

3.1、创建一个实体类

package com.study.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String username;
    private String password;
    private String role;
}

3.2、创建一个dao

package com.study.dao;

import com.study.entity.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserInfoDao extends JpaRepository<UserInfo, Long> {
    UserInfo findByUsername(String name);
}

3.3、创建service层的类 接口和实现类

package com.study.service;
import com.study.entity.UserInfo;

public interface UserInfoService {
    UserInfo findUserInfo(String username);
}
package com.study.service.impl;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import com.study.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    UserInfoDao userInfoDao;

    public UserInfo findUserInfo(String username) {
        UserInfo userInfo = userInfoDao.findByUsername(username);
        return userInfo;
    }
}

3.4、配置数据库连接信息

spring.datasource.url=jdbc:mysql://8.129.121.241:3306/springsecurity?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=xxyy
spring.datasource.password=xxYY11..
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring-data-jpa
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database=mysql

3.5、初始化数据库数据

package com.study.init;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class JdbcInit {
    @Autowired
    private UserInfoDao userInfoDao;

    @PostConstruct
    public void init() {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("lisi");
        userInfo.setPassword(passwordEncoder.encode("lisi"));
        userInfo.setRole("normal");
        userInfoDao.save(userInfo);
    }
}

3.6、查询数据库,构造一个User对象,用于框架中使用

package com.study.provider;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class MyUserDetailService implements UserDetailsService {
    @Autowired
    private UserInfoDao userInfoDao;
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user=null;
        UserInfo userInfo=null;
        if(username!=null){
            userInfo = userInfoDao.findByUsername(username);
            if (userInfo!=null){
                List<GrantedAuthority> list=new ArrayList<GrantedAuthority>();
                GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_"+userInfo.getRole());
                list.add(authority);
                user=new User(userInfo.getUsername(),userInfo.getPassword(),list);
            }
        }
        return user;
    }
}

4、编写配置类,将通过数据库得到的User对象,进行角色配置

package com.study.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

5、添加Controller,最后测试验证,注意将添加数据库信息的注解注释掉

package com.study.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping(value = "/hello")
    public String hello() {
        return "hello spring-security";
    }

    @RequestMapping(value = "/hellouser")
    @PreAuthorize(value = "hasAnyRole('ROLE_admin','ROLE_normal')")
    public String helloUser() {
        return "hello spring-security have normail Admin role";
    }

    @RequestMapping(value = "/helloadmin")
    @PreAuthorize(value = "hasAnyRole('ROLE_admin')")
    public String helloAdmin() {
        return "hello spring-security have Admin role";
    }
}

踩坑

所有的权限都要加上 “ROLE_” 作为前缀

基于角色权限

认证和授权

  1. authentication:认证,认证访问者是谁。一 个用户或者一个其他系统是不是当前要访问的系统中的有效用户。

  2. authorization:授权,访问者能做什么?
    比如说张三用户要访问一个公司OA系统。首先系统要判断张三 是不是公司中的有效用户

  3. 例如:认证:张三是不是有效的用户,是不是公司的职员
    授权:判断张三能否做某些操作,如果张三是个领导可以批准下级的请假,其他的操作

RBAC是什么?

image-20210523153320553
  1. 权限:能对资源的操作,比如增加, 修改,删除,查看等等

  2. 角色:自定义的,表示权限的集合。一个角色可以有多个权限

  3. 用户:一个用户赋予某种权限,就等同于拥有这些权限

RBAC设计中的表

  1. 用户表:用户认证(登录用到的表)
    用户名,密码,是否启用,是否锁定等信息

  2. 角色表:定义角色信息
    角色名称,角色的描述

  3. 用户和角色的关系表:用户和角色是多对多的关系
    一个用户可以有多个角色,一个角色可以有多个用户

  4. 权限表,角色和权限的关系表
    角色可以有哪些权限

spring security中认证的接口和类

UserDetails 接口

表示用户信息

// 接口,表示用户信息
public interface UserDetails extends Serializable {
	// 权限集合
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();
	// 账号是否过期
    boolean isAccountNonExpired();
	// 账号是否锁定
    boolean isAccountNonLocked();
	// 证书是否过期
    boolean isCredentialsNonExpired();
	// 账号是否启用
    boolean isEnabled();
}

UserDetails实现类

package org.springframework.security.core.userdetails.User;

可以自定义类实现UserDetails接口,作为你的系统中的用户类。这个类可以交给spring security使用

UserDetailsService接口

主要作用:
获取用户信息,得到是UserDetails对象。一般项目中都需要自定义类实现这个接口,从数据库中获取数据

只有一个方法需要实现:
UserDetails loadUserByUsername(String var1) : 根据用户名称,获取用户信息(用户名称,密码,角色结合,是否可用,是否锁定等信息)

UserDetailsService接口的实现类类:

1、InMemoryUserDetailsManager :在管理内存中用户信息
优点:使用方便
缺点:数据不是持久的,系统重启后数据恢复原样

2、JdbcUserDetailsManager:用户信息存放在数据库中,底层使用jdbcTemplate操作数据库。
可以 使用JdbcUserDetailsManager中的方法完成用户的管理
createUser:创建用户
updateUser:更新用户
deleteUser:删除用户
UserExists:判断用户是否存在

数据库文件:

package org.springframework.security.core.userdetails.jdbc;
  • users.ddl 文件
create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);
create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);

注:建表时若使用的是MySQL,将varchar_ignorecase替换为varchar

使用案例-1

  • 在管理内存中用户信息

1、创建一个项目

2、加入maven坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.5</version>
</dependency>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

3、创建应用的配置类

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

    @Bean
    public UserDetailsService userDetailsService() {
        PasswordEncoder encoder = passwordEncoder();
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("admin")
                .password(encoder.encode("admin"))
                .roles("ADMIN", "USER").build());
        manager.createUser(User.withUsername("zs")
                .password(encoder.encode("zs"))
                .roles("USER").build());
        return manager;
    }
}

4、创建类继承WebSecuri tyConfi gurerAdapter

public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService detailsService=null;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.userDetailsService(detailsService);
    }
}

5、测试

使用案例-2

  • 使用访问数据库,获取认证的用户信息

1、创建项目

2、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>2.4.5</version>
</dependency>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

3、创建应用的配置类,创建JdbcUserDetatilsService对象

@Configuration
public class ApplicationConfig {
    //通过spring容器注入 DataSource
    @Autowired
    private DataSource dataSource;

    //创建PasswordEncoder对象
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //创建JdbcUserDetatilsService对象
    @Bean(name = "jdbcUserDetatilsService")
    public UserDetailsService jdbcUserDetatilsService() {
        System.out.println("===dataSource===" + dataSource);
        PasswordEncoder encoder = passwordEncoder();
        //初始数据源DataSource --- JdbcTemplate对象
        JdbcUserDetailsManager manager = new JdbcUserDetailsManager(dataSource);
        //如果数据库中已经存在账号不添加
        if (!manager.userExists("admin")) {
            manager.createUser(User.withUsername("admin")
                    .password(encoder.encode("admin"))
                    .roles("ADMIN", "USER", "MANAGER").build());
        }
        if (!manager.userExists("zs")) {
            manager.createUser(User.withUsername("zs").
                    password(encoder.encode("zs"))
                    .roles("USER").build());
        }
        if (!manager.userExists("ls")) {
            manager.createUser(User.withUsername("ls")
                    .password(encoder.encode("ls"))
                    .roles("USER", "NORMAL").build());
        }
        return manager;
    }
}

4、创建一个security的配置,自定义安全配置信息。指定JdbcUserDetatilsService类

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    @Qualifier("jdbcUserDetatilsService")
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.userDetailsService(userDetailsService);
    }
}

5、修改application.properties文件 连接数据库。配置数据源DataSource

spring.datasource.url=jdbc:mysql://8.129.121.241:3306/t-ssm?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=xxyy
spring.datasource.password=xxYY11..
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

6.测试

使用案例-3

  • 自定义角色信息(定义”用户、角色、关系“三张表)

文章来源:https://www.cnblogs.com/littleleopard/p/14800320.html

后台-系统设置-扩展变量-手机广告位-内容正文底部
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文地址:https://www.jcdi.cn/qtbc/30576.html

留言与评论(共有 0 条评论)
   
验证码:
后台-系统设置-扩展变量-手机广告位-评论底部广告位

教程弟

https://www.jcdi.cn/

统计代码 | 京ICP1234567-2号

Powered By 教程弟 教程弟

使用手机软件扫描微信二维码