前言:
Spring Security对Web安全性的支持大量地依赖于Servlet过滤器。这些过滤器拦截进入请求,并且在应用程序处理该请求之前进行某些安全处理。 Spring Security提供有若干个过滤器,它们能够拦截Servlet请求,并将这些请求转给认证和访问决策管理器处理,从而增强安全性。根据自己的需要,可以使用适当的过滤器来保护自己的应用程序。
如果使用过Servlet过滤器且令其正常工作,就必须在Web应用程序的web.xml文件中使用 和元素配置它们。虽然这样做能起作用,但是它并不适用于使用依赖注入进行的配置。
FilterToBeanProxy是一个特殊的Servlet过滤器,它本身做的工作并不多,而是将自己的工作委托给Spring应用程序上下文 中的一个Bean来完成。被委托的Bean几乎和其他的Servlet过滤器一样,实现javax.servlet.Filter接 口,但它是在Spring配置文件而不是web.xml文件中配置的。
实际上,FilterToBeanProxy代理给的那个Bean可以是javax.servlet.Filter的任意实现。这可以是 Spring Security的任何一个过滤器,或者它可以是自己创建的一个过滤器。但是正如本书已经提到的那样,Spring Security要求至少配置四个而且可能一打或者更多的过滤器。说白了了就是权限,认证 拦截
准备
项目 Springboot+SpringSecurity
依赖坐标
<!--spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
创建 配置类
在前端 账号密码 username 和password 这个 两个字段
package com.tang.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.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author
* @className: SecurityConfig
* @description: TODO 类描述
* @create 2021-10-24 12:46 下午
* @desc
**/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//通过数据库查询用户
@Autowired
UserDetailsService userDetailsService;
//设置用户名 密码 权限
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//加密
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String user = bCryptPasswordEncoder.encode("user");
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")//登录访问的路径
.defaultSuccessUrl("/user/index").permitAll()//登录成功访问路径
.and().authorizeRequests()
.antMatchers("/","/test/security","/user/login").permitAll()//设置路径可以访问不需要验证
//匹配单个权限
.antMatchers("/test/index").hasAuthority("admin")
//设置访问权限多个..........
.antMatchers("/test/index").hasAnyAuthority("admin,test")
//业务匹配 ROLE_test
.antMatchers("/test/index").hasAnyRole("test")
//多匹配 ROLE_admin ROLE_test......
.antMatchers("/test/index").hasAnyRole("admin,test")
.anyRequest().authenticated()//
.and().csrf().disable();//关闭保护
}
}
service层
通过数据库查询账号密码
package com.tang.springsecurity.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tang.springsecurity.mapper.UserMapper;
import com.tang.springsecurity.pojo.Users;
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.GregorianCalendar;
import java.util.List;
/**
* @author
* @className: MyUserServiceImpl
* @description: TODO 类描述
* @create 2021-10-24 8:29 下午
* @desc
**/
@Service("userDetailsService")
public class MyUserServiceImpl implements UserDetailsService {
@Autowired
UserMapper userMapper;
/**
* 登录
* @param username 用户名
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询条还
QueryWrapper<Users> wrapper=new QueryWrapper<>();
wrapper.eq("username",username);
Users users = userMapper.selectOne(wrapper);
//账号不存在
if (users==null){
return (UserDetails) new UsernameNotFoundException("账号不存在");
}
//权限设置
List<GrantedAuthority> list= AuthorityUtils.createAuthorityList("admin");
// 验证登录
return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getUserpassword()),list);
}
}
除了配置权限还可以使用注解的方式
使用注解 必须在启动类或者配置类上添加@EnableGlobalMethodSecurity(prePostEnabled = true)注解 对SpringSecurity 启用
package com.tang.springsecurity.controller;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.tang.springsecurity.pojo.Users;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 测试 SpringSecurity
*/
@RestController
@RequestMapping("test")
public class SecurityTest {
//测试security的验证 在浏览器上拦截请求 首先是进入 security的默认页面 登录 进去在访问接口 过滤器链
@GetMapping("security")
public String getTest(){
return "测试";
}
/**
*/
@RequestMapping("index")
public String tests(){
return "登录后访问";
}
/**
* 注解权限验证
* @return
*/
@GetMapping("select")
@Secured("ROLE_test")
public String select(){
return "权限";
}
/**
* 进入方法前校验权限
* @return
*/
@GetMapping("select1")
@PreAuthorize("hasAuthority('admin')")
public String select2(){
return "进入方法前校验权限";
}
/**
* 进入方法后校验权限
* @return
*/
@GetMapping("select2")
@PostAuthorize("hasAnyAuthority('test')")
public String select3(){
return "进入方法后校验";
}
/**
* 对返回数据做权限处理
* @return
*/
@GetMapping("select3")
@PreAuthorize("hasAuthority('admin')")
@PostFilter("filterObject.username=='a'")
public List<Users> select4(){
List<Users> list=new ArrayList<>();
Users users = new Users();
Users users1 = new Users();
users1.setUsername("a");
list.add(users1);
users.setUsername("b");
list.add(users);
System.out.println(list);
return list;
}
}
待续…