用户在进行资源访问时,要求系统要对用户进行权限控制,其具体流程如图-1所示:
鸟瞰SpringSecurity 基本技术架构,例如:
绿色部分是认证过滤器,需要我们自己配置,可以配置多个认证过滤器。认证过滤器可以使用 Spring Security 提供的认证过滤器,也可以自定义过滤器(例如:短信验证)。认证过滤器要在 configure(HttpSecurity http)方法中配置,没有配置不生效。下面会重点介绍以下三个过滤器:
UsernamePasswordAuthenticationFilter 过滤器:该过滤器会拦截前端提交的 POST 方式的登录表单请求,并进行身份认证。
BasicAuthenticationFilter:检测和处理 http basic 认证。
ExceptionTranslationFilter 过滤器:该过滤器不需要我们配置,对于前端提交的请求会直接放行,捕获后续抛出的异常并进行处理(例如:权限访问限制)。
FilterSecurityInterceptor 过滤器:该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否有权限访问对应的资源。如果访问受限会抛出相关异常,并由 ExceptionTranslationFilter 过滤器进行捕获和处理。
================================================================
创建security项目,其pom.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?><project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
4.0.0
spring-boot-starter-parent
org.springframework.boot
2.3.2.RELEASE
com.cy
05-security
1.0-SNAPSHOT
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
第一步:创建项目,其pom.xml文件核心依赖如下:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-security
第二步:启动服务(依赖添加以后会默认添加一个tomcat,端口8080)
服务启动之后,你会发现,控制台会出现一个随机的密码,用于访问当前系统,默认用户名是user,密码就是控制台上的密码,如图所示:
服务启动后,打开浏览器进行访问,如图所示:
输入账号(默认用户名为user)和密码登陆成功默认为如下页面.
其中,出现这个页面表示还没有配置登陆成功页面,这个资源页面现在还不存在,可以在项目的resources目录下创建st
必看视频!获取2024年最新Java开发全套学习资料
atic目录(假如没有此目录),然后在此目录下创建index.html页面,内容如下:
The Index Page
此时,再次启动服务进行登陆,呈现登陆成功的效果,如图所示:
=================================================================
定义配置类,基于此类配置认证和授权逻辑,例如:
package com.cy.security.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
-
认证授权管理器对用户输入的密码与数据库中存储的密码进行比对时,
-
需要对这个密码加密,加密算法需要我们自己指定
-
@return
*/
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
//关闭跨域攻击
http.csrf().disable();
//自定义登陆表单
http.formLogin().loginPage(“/login.html”).loginProcessingUrl(“/login”);
//请求资源的认证配置
http.authorizeRequests()
.antMatchers(“/login”,“/login.html”)
.permitAll()
.anyRequest().authenticated();
}
}
定义数据访问层对象,基于此对象实现用户及用户权限信息的获取,例如:
package com.cy.security.dao;
import com.cy.security.domain.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
/**
-
基于用户名获取用户信息
-
@param username
-
@return
*/
@Select("select id,username,password,status " +
"from tb_users " +
“where username=#{username}”)
SysUser selectUserByUsername(String username);
/**
-
基于用户id查询用户权限
-
@param userId 用户id
-
@return 用户的权限
-
涉及到的表:tb_user_roles,tb_role_menus,tb_menus
*/
@Select("select distinct m.permission " +
“from tb_user_roles ur join tb_role_menus rm on ur.role_id=rm.role_id” +
" join tb_menus m on rm.menu_id=m.id " +
“where ur.user_id=#{userId} and m.permission is not null”)
List selectUserPermissions(Long userId);
}
Spring Security 提供了一个UserDetailService接口,我们可以基于此接口实现类,实现用户信息的获取和封装,例如:
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
/**
-
客户端点击登陆时,添加些用户信息会传给此方法
-
@param username
-
@return
-
@throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1.基于用户名查询用户信息
SysUser user=userMapper.selectUserByUsername(username);
//…判断自己写…
System.out.println(user);
//2.查询用户登陆用户权限
List permissions=userMapper.selectUserPermissions(user.getId());
System.out.println(permissions);
//3.封装用户信息并返回,将用户信息交给认证管理器,认证授权管理器负责对用户输入的信息进行认证和授权
List authorityList =
AuthorityUtils.createAuthorityList(permissions.toArray(new String[]{}));
return new User(username, user.getPassword(),authorityList);
}
}
在resources的static目录下创建login.html页面,例如:
<!doctype html>
integrity=“sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC” crossorigin=“anonymous”>
Please Login
<button type=“button” @click=“doLogin()” class=“btn btn-primary”>Submit