spring spring-security

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

入门案例

1、新建工程,导入依赖

org.springframework.bootspring-boot-starter-security

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

登陆名:user

密码:查看日志

Spring-Security_Spring-Security

3、小结

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

security相关配置

自定义用户名和密码

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

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

关闭验证

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

Spring-Security_Spring-Security_02

使用内存中的账户

使用类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、导入依赖

mysqlmysql-connector-java8.0.23org.springframework.bootspring-boot-starter-data-jpa2.4.5

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 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){
                Listlist=new ArrayList();
                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_” 作为前缀

未完待续