Spring-Security本质是一个过滤器链,有很多的过滤器
通过查看源码
FilterSecurityIntercepter //这是一个方法级的权限过滤器,基本位于过滤链的最底部
ExceptionTranslationFilter //这是个异常过滤器,用来处理再认证授权时过程中抛出的异常
UsernamePasswordAuthenticationFilter //这是一个对/login的POST请求做拦截,校验表单中的用户名和密码等功能
1、创建类继承UsernamePasswordAuthenticationFilter,重写里的三个方法
2、创建类实现UserDetailService,编写查询数据过程,返回User对象,这个User对象是安全框架提供的对象
设置登录的用户名和密码:第一种方式:通过配置文件。第二种方式:通过配置类。第三种方式:自定义编写实现类
在这里插入图片描述
spring.security.user.name=admin
spring.security.user.password=123456
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService uds; //注入用户服务信息
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();
auth.userDetailsService(uds).passwordEncoder(bpe);
}
}
@Service("uds")
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> authn = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_admin");
return new User("username",
new BCryptPasswordEncoder().encode("123456"),authn);
}
}
这里需要整合mybatisPlus完成数据库操作或者jdbc
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.0.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
package entity;
import lombok.Data;
public class Users {
private int id;
private String username;
private String password;
@Override
public String toString() {
return "Users{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public Users() {
}
public Users(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.hxzy.springscuritydamo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import entity.Users;
import org.springframework.stereotype.Repository;
/**
* @BaseMapper 这个接口里实现了对数据库的增删改查操作,直接调用里面的方法就可以了
* @Repository
* */
@Repository
public interface UserMapper extends BaseMapper<Users> {
}
package com.hxzy.springscuritydamo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hxzy.springscuritydamo.mapper.UserMapper;
import entity.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.ArrayList;
import java.util.List;
@Service("uds")
public class MyUserDetailService implements UserDetailsService {
@Autowired
private UserMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//调用userMapper方法,根据用户名查询数据库
QueryWrapper<Users> wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
Users users = usersMapper.selectOne(wrapper);
//判断
if (users == null){
//如果数据库里没有用户名,则认证失败
throw new UsernameNotFoundException("用户不存在");
}
//查数据库,得到密码,得到用户名,得到s权限
List<GrantedAuthority> authn = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_admin");
return new User(users.getUsername(),
new BCryptPasswordEncoder().encode(users.getPassword()),authn);
}
}
package com.hxzy.springscuritydamo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.hxzy.springscuritydamo.mapper")
@SpringBootApplication
public class SpringscuritydamoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringscuritydamoApplication.class, args);
}
}
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
package com.hxzy.springscuritydamo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
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.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
import java.beans.PersistenceDelegate;
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService uds; //注入用户服务信息
@Autowired
private DataSource dataSource;//注入数据源
//配置对象
@Bean
public PersistentTokenRepository ptr(){
JdbcTokenRepositoryImpl jtr = new JdbcTokenRepositoryImpl();
jtr.setDataSource(dataSource);
// jtr.setCreateTableOnStartup(true);
return jtr;
}
// @Override
// public void addViewControllers(ViewControllerRegistry registry){
// registry.addViewController("/").setViewName("forword:/login.html");
// registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
// }
//实现用户身份认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();
auth.userDetailsService(uds).passwordEncoder(bpe);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置Url的权限访问
// http.authorizeRequests()
// .antMatchers("/").permitAll()
// .antMatchers("/**update**").permitAll()
// .antMatchers("login/**").permitAll()
// .anyRequest().authenticated();
http.csrf().disable(); //关闭csrf防护
//配置没有访问权限页面403页面
http.exceptionHandling().accessDeniedPage("/error.html");
//安全退出
http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/login").permitAll();
//loginpage()->自定义登录页面设置,loginProcessingUrl()->登录访问的路径,defaultSuccessUrl()->登录成功后访问的页面
http.formLogin().loginPage("/test/login")//自己配置的登录页面
.loginProcessingUrl("/user/login")
.defaultSuccessUrl("/test/index")
.failureUrl("/test/error").permitAll()
.and().authorizeRequests()
.antMatchers("/","/test/hello","/user/login").permitAll() //设置哪些路径可以直接访问,不需要认证
//1、hasAuthority:当前登录用户,只有具有admins权限的用户才能访问这个路径
//.antMatchers("/test/index").hasAuthority("admins")
//2、hasAnyAuthority:当前登录用户,自定义权限的用户才能访问这个路径
//.antMatchers("/test/index").hasAnyAuthority("admins,manager")
//3、hasRole:
//.antMatchers("/test/index").hasRole("saler")
//4、hasAnyRole:
.antMatchers("/test/index").hasAnyRole("sale,manager,admin,user")
.anyRequest().authenticated()
}
}
(2)创建相关页面/test/login、/test/index
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
form{
width: 240px;
}
span{
display: block;
margin-top: 10px;
}
input{
float: right;
}
style>
head>
<body>
<form action="/user/login" method="post">
<span>用户名:<input type="text" name="username" />span>
<span>密码:<input type="password" name="password" />span>
<span>单点登录<input style="float: none" type="checkbox" name="remember-me" />span>
<input style="cursor: pointer;" type="submit" value="登录" />
form>
body>
html>
4个方法:hasAuthority()、hasAnyAuthority()、hasRole()、hasAnyRole()
http.antMatchers("test/index").hasAuthortiy("admins")
List<GrantedAuthority> authn = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
如果访问地址的权限与返回User对象权限不一致,则跳到403界面无权访问
.antMatchers("/test/index").hasAnyAuthority("admins,manager");
List<GrantedAuthority> authn = AuthorityUtils.commaSeparatedStringToAuthorityList("admins");