概述
- 认证(你是谁,户/设备/系统
- 验证(你能干什么,也叫权限控制/授权,允许执行的操作)
- 基于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控制安全管理内容
- 自定义类继承WebSecurityConfigurerAdapter,声明是个配置类、开启WebSecurity
- 重写configure方法
- 在SpringSecurity_v5.0版本中,密码必须使用一个加密方式
- 构建一个方法创建一个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_” 作为前缀
未完待续