Spring Security 认证授权安全框架

news/2024/9/8 11:04:10

Spring Security概述

1.什么是Spring Security?

Spring Security是一个Java框架,用于保护应用程序的安全性。它提供了一套全面的安全解决方案,包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念,可以轻松地集成到任何基于Spring的应用程序中。它支持多种身份验证选项和授权策略,开发人员可以根据需要选择适合的方式。此外,Spring Security还提供了一些附加功能,如集成第三方身份验证提供商和单点登录,以及会话管理和密码编码等。总之,Spring Security是一个强大且易于使用的框架,可以帮助开发人员提高应用程序的安全性和可靠性。

什么是授权

这个根据用户的权限来控制用户使用资源的过程就是授权。

为什么要授权

认证是为了保护用户身份的合法性,授权则是为了更细的粒度的对隐私数据经行划分,授权是在认证通过后发生的,控制不同的用户能够访问不同的资源;

授权:授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问;

Spring Security入门体验

一.快速搭建Spring Security安全框架项目;

1.1--创建一个SpringBoot项目;

1.2--修改SpringBoot的版本号,并修改jdk版本号;

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>SpringSecurity001</artifactId><version>0.0.1-SNAPSHOT</version><name>SpringSecurity001</name><description>SpringSecurity001</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version><!--SpringBoot版本号   这里使用的JDK版本为8--></properties><dependencies><!--引入Spring Security安全框架依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--添加lombok依赖  实体类的get set方法生成--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--测试依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.aaa.SpringSecurity001Application</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

1.3--引入SPringleSecurity依赖;

<!--引入Spring Security安全框架依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

1.4--创建一个HelloController,Controller层定义一个资源;

1.5--启动项目并访问资源路径;

访问路径:http://localhost:8080/hello

注:我们发现使用了security后在访问我们自己的接口,security会拦截并跳转到认证页面,认证后才可以访问。默认认证的账号uer密码在控制台;

二.创建Spring Security自定义账户和密码;

我们刚才使用的是security自带的账户和密码,我们自己也可以自定义账户和密码;

2.1--在application.properties配置文件中定义一个账户和密码;

自定义账户和密码文件如下:

#创建Spring Security自定义账户和密码#账户
spring.security.user.name=admin
#密码
spring.security.user.password=123456
server.port=8080

注:配置完自定义文件和密码,重启运行,这是控制台中没有密码(控制台不会生成密码);

注:这种方式只能定义一个账户和密码,无法定义多个账户和密码;

三.自定义多个账户和密码

在配置文件中,只能定义一个账户和密码。我们可以定义一个配置类,完成多个账号和密码的定义;

1.创建Config层 MysecurityConfig;

配置类内容

package com.aaa.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication() //基于内存创建的账户和密码  未来可以用来连接数据库//账户.withUser("zhangsan")//密码.password("123456")//用户具备的角色.roles("admin").and() //连接符.withUser("lisi").password("012345").roles("test").and().withUser("wangwu").password("567890").roles("group");}
}

注:如果使用了配置类,那么之前在配置文件中定义的账户和密码不在生效;

控制台错误提示:需要给它指定的加密器;

解决方式:添加加密器

//可以把该方法返回的对象交于Spring容器管理@Beanpublic PasswordEncoder passwordEncoder(){return  new BCryptPasswordEncoder();}
package com.aaa.config;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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {//可以把该方法返回的对象交于Spring容器管理@Beanpublic PasswordEncoder passwordEncoder(){return  new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication() //基于内存创建的账户和密码  未来可以用来连接数据库//账户.withUser("zhangsan")//密码.password(passwordEncoder().encode("123456"))//用户具备的角色.roles("admin").and() //连接符.withUser("lisi").password(passwordEncoder().encode("012345")).roles("test").and().withUser("wangwu").password(passwordEncoder().encode("567890")).roles("group");}
}

注:把明文密码通过加密器经行加密;

再次访问资源

四.密码加密器

密码加密器,可以把把明文转换为密文 encode

同时也可以匹配密码 matches;

package com.aaa.Test;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;public class test {public static void main(String[] args) {//创建加密器对象PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();//使用加密器String encode = passwordEncoder.encode("123456");System.out.println(encode);//匹配密码  第一个参数是客户输得密码   第二个参数是加密器密文//把客户输得密码和加密过的密码经行比对是否一致,一致返回true,不一致返回flase;boolean matches = passwordEncoder.matches("123456", encode);//结果为trueSystem.out.println(matches);   }
}

 

问题:对称加密和非对称加密

答:对称加密:加密和解密使用的密钥是同一个; --这种加密的方式可以破解

      非对称加密: 加密和解密使用的密钥不是同一个;--这种加密的方式无法破解

五.获取当前用户的信息

获取登录成功者的信息

package com.aaa.Controller;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello")public String hello(){return "hello资源·······";}@GetMapping("/info")public Authentication info(){//把当前信息保存到SecurityContext类中;SecurityContext securityContext = SecurityContextHolder.getContext();//把当前用户封装到Authentication类中  账户  密码 权限 角色等信息Authentication authentication = securityContext.getAuthentication();return authentication;}
}

Security框架会把当前用户信息封装到Authentication中,并把该类对象存放到SecurityContext中;

访问资源路径http://localhost:8080/info

六.修改它的登录页面

默认security提供了一个登录页面,如果不想使用它提供的页面,我们可以指定我们自己的登录页面;

1.自己在static静态资源文件下创建一个登录页面;

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页</title><style>body {background-color: #222;font-family: Arial, sans-serif;color: #fff;display: flex;align-items: center;justify-content: center;height: 100vh;}.login-container {background-color: #333;padding: 40px;border-radius: 10px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);}h1 {text-align: center;}.form-group {margin-bottom: 20px;}.form-group label {display: block;margin-bottom: 5px;}.form-group input[type="text"],.form-group input[type="password"] {width: 100%;padding: 10px;border-radius: 5px;border: none;background-color: #555;color: #fff;}.form-group input[type="submit"] {width: 100%;padding: 10px;border-radius: 5px;border: none;background-color: #007bff;color: #fff;cursor: pointer;transition: background-color 0.3s ease;}.form-group input[type="submit"]:hover {background-color: #0056b3;}</style>
</head>
<body>
<div class="login-container"><h1>Welcome to Cool Login Page</h1><form action="login" method="post"><div class="form-group"><label for="username">Username:</label><!--账户--><input type="text" id="username" name="username" required></div><div class="form-group"><label for="password">Password:</label><!--密码--><input type="password" id="password" name="password" required></div><div class="form-group"><input type="submit" value="Login"></div></form>
</div>
</body>
</html>

2.修改security配置类;在config层 HelloConfig文件中重写configure方法;

 @Overrideprotected void configure(HttpSecurity http) throws Exception {//设置表单登录信息http.formLogin()//设置自己的登录页面.loginPage("/login.html")//设置登录表单的提交路径 要和login.html中的action一致.loginProcessingUrl("/login")//这个页面允许放行.permitAll();//禁止跨域伪造请求验证http.csrf().disable();//其他请求路径都要认证http.authorizeRequests().anyRequest().authenticated();}

访问路径访问info或者hello都可以进入到自己的登录页面;

七.设置跳转登录成功页面

默认登录成功 / 或原来的访问路径

创建SuccessController

package com.aaa.Controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@Controller
public class SuccessController {@PostMapping("/success")public String success(){return "redirect:/success.html";}
}

创建一个success.html登录成功页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

输入账号和密码

登录成功

授权的实现

授权:用户具有的权限和资源绑定的过程就是授权;

第一步:修改config  MySecurityConfig配置文件

 第二步:创建自定义资源访问  controller层  AuthController资源文件

package com.aaa.Controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;//资源
@RestController
public class AuthController {@GetMapping("select")public String select(){System.out.println("查询资源");return "查询资源";}@GetMapping("update")public String update(){System.out.println("修改资源");return "修改资源";}@GetMapping("delete")public String delete(){System.out.println("删除资源");return "删除资源";}@GetMapping("xxx")public String xxx(){System.out.println("共享资源");return "共享资源";}
}

第三步: 权限和资源进行绑定   config  MySecurityConfig配置文件

package com.aaa.config;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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {//可以把该方法返回的对象交于Spring容器管理@Beanpublic PasswordEncoder passwordEncoder(){return  new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {//设置表单登录信息http.formLogin()//设置自己的登录页面.loginPage("/login.html")//设置登录表单的提交路径 要和login.html中的action一致.loginProcessingUrl("/login")//表示登录成功跳转路径 提交方式必须为post请求.successForwardUrl("/success")//这个页面允许放行.permitAll();//设定资源和权限进行绑定http.authorizeRequests().antMatchers("/select").hasAnyAuthority("user:select").antMatchers("/update").hasAnyAuthority("user:update").antMatchers("/delect").hasAnyAuthority("user:delect").antMatchers("/xxx").hasAnyAuthority("user:xxx");//异常处理页面http.exceptionHandling().accessDeniedPage("/403.html");//禁止跨域伪造请求验证http.csrf().disable();//其他请求路径都要认证http.authorizeRequests().anyRequest().authenticated();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication() //基于内存创建的账户和密码  未来可以用来连接数据库//账户.withUser("zhangsan")//密码.password(passwordEncoder().encode("123456"))//用户具备的角色.roles("admin")//设定用户权限.authorities("user:select","user:update","user:delete").and() //连接符.withUser("lisi").password(passwordEncoder().encode("012345")).roles("test").authorities("user:xxx").and().withUser("wangwu").password(passwordEncoder().encode("567890")).roles("group");}
}

第四步:访问资源

上面再访问没有的权限资源时,出现上面的错误界面,这种界面对客户友好。跳转到一个权限不足的界面;  

使用security注解完成授权

(思考: 上面权限和资源得到绑定 需要手动一一绑定。真正再开发中我们具有的权限和资源是非常多的。如果手动一一绑定是很麻烦的。)

第一步:开启security权限注解驱动

第二步:再相应的资源上使用注解  

controller层  AuthController资源文件

package com.aaa.Controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;//资源
@RestController
public class AuthController {@GetMapping("select")@PreAuthorize(value = "hasAuthority('user:select')")public String select(){System.out.println("查询资源");return "查询资源";}@GetMapping("update")@PreAuthorize(value = "hasAuthority('user:upate')")public String update(){System.out.println("修改资源");return "修改资源";}@GetMapping("delete")@PreAuthorize(value = "hasAuthority('user:delete')")public String delete(){System.out.println("删除资源");return "删除资源";}@GetMapping("xxx")@PreAuthorize(value = "hasAuthority('user:xxx')")public String xxx(){System.out.println("共享资源");return "共享资源";}
}

第三步:修改security配置

第四步:访问资源,流程是一样的  略

了解security认证的流程(源码)

核心过滤器:UsernamePasswordAuthenticationFilter

 

使用Spring Security连接数据库(自定义认证--需要连接数据库)

第一步:创建securtiy数据库

DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission`  (`perid` int(0) NOT NULL AUTO_INCREMENT,`pername` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`percode` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (`perid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_permission
-- ----------------------------
INSERT INTO `sys_permission` VALUES (1, '用户查询', 'user:query');
INSERT INTO `sys_permission` VALUES (2, '用户添加', 'user:add');
INSERT INTO `sys_permission` VALUES (3, '用户修改', 'user:update');
INSERT INTO `sys_permission` VALUES (4, '用户删除', 'user:delete');
INSERT INTO `sys_permission` VALUES (5, '用户导出', 'user:export');-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (`roleid` int(0) NOT NULL AUTO_INCREMENT,`rolename` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (`roleid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, '管理员');
INSERT INTO `sys_role` VALUES (2, '测试人员');
INSERT INTO `sys_role` VALUES (3, '普通用户');-- ----------------------------
-- Table structure for sys_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission`  (`perid` int(0) NULL DEFAULT NULL,`roleid` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_role_permission
-- ----------------------------
INSERT INTO `sys_role_permission` VALUES (2, 1);
INSERT INTO `sys_role_permission` VALUES (1, 1);
INSERT INTO `sys_role_permission` VALUES (3, 1);
INSERT INTO `sys_role_permission` VALUES (4, 1);
INSERT INTO `sys_role_permission` VALUES (2, 2);
INSERT INTO `sys_role_permission` VALUES (1, 2);
INSERT INTO `sys_role_permission` VALUES (3, 2);
INSERT INTO `sys_role_permission` VALUES (1, 3);
INSERT INTO `sys_role_permission` VALUES (5, 3);-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (`userid` int(0) NOT NULL AUTO_INCREMENT,`username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`userpwd` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`sex` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`address` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (`userid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, '张三', '$2a$10$cI7e7bgSs9.9nNHhxKO9LuK/Ll.AeZwgUyZb77oD2y3UwwZyZhWG6', '男', '郑州');
INSERT INTO `sys_user` VALUES (2, '李四', '$2a$10$cI7e7bgSs9.9nNHhxKO9LuK/Ll.AeZwgUyZb77oD2y3UwwZyZhWG6', '男', '北京');
INSERT INTO `sys_user` VALUES (3, '王五', '$2a$10$cI7e7bgSs9.9nNHhxKO9LuK/Ll.AeZwgUyZb77oD2y3UwwZyZhWG6', '女', '杭州');-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`  (`userid` int(0) NOT NULL,`roleid` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (1, 1);
INSERT INTO `sys_user_role` VALUES (2, 2);
INSERT INTO `sys_user_role` VALUES (3, 3);
INSERT INTO `sys_user_role` VALUES (1, 2);SET FOREIGN_KEY_CHECKS = 1;

 

第二步:创建一个SpringBoot项目--------引入相关的依赖(lombok依赖   mysql驱动依赖  mybatis-plus依赖,security启动依赖)

 <dependencies><!--加入security安全框架依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--lombok依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mysql驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis-plus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

第三步:创建实体类   entity层 (User  Role  Permission)

User实体类

package com.aaa.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("sys_user")   //实体类和数据库表名不一致时,使用该注解进行映射
public class User {@TableId(type = IdType.AUTO)    //主键自增private Integer userid;private String username;private String userpwd;private String sex;private String address;
}

Role实体类

package com.aaa.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("sys_role")    //实体类和数据库表名不一致时,使用该注解进行映射
public class Role {@TableId(type = IdType.AUTO)    //主键自增private Integer roleid;private  String rolename;
}

Permission实体类

package com.aaa.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("sys_permission")    //实体类和数据库表名不一致时,使用该注解进行映射
public class Permission {@TableId(type = IdType.AUTO)    //主键自增private Integer perid;private String pername;private String percode;
}

第四步:创建相应的Dao接口   Dao层  (UserDao  RoleDao  PermissionDao)

UserDao接口

package com.aaa.dao;import com.aaa.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserDao extends BaseMapper<User> {}

ReloDao接口

package com.aaa.dao;import com.aaa.entity.Role;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface RoleDao extends BaseMapper<Role> {
}

PermissionDao接口

package com.aaa.dao;import com.aaa.entity.Permission;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;import java.util.List;public interface PermissionDao extends BaseMapper<Permission> {//查找用户的权限@Select("select distinct p.* from sys_user_role u join sys_role_permission r on u.roleid=r.roleid join sys_permission p on r.perid=p.perid where userid=#{userId}")public List<Permission> selectByUserId(Integer userId);}

第五步:创建业务层 Service     MyUserDetailService代码

package com.aaa.service;import com.aaa.dao.PermissionDao;
import com.aaa.dao.UserDao;
import com.aaa.entity.Permission;
import com.aaa.entity.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Collection;
import java.util.List;@Service
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate UserDao userDao;@Autowiredprivate PermissionDao permissionDao;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//1. 根据账户查找用户信息QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",username);User user = userDao.selectOne(queryWrapper);//2.判断用户是否为nullif(user!=null){//3.查找用户的具体权限List<Permission> permissions = permissionDao.selectByUserId(user.getUserid());/*** String username, 账户* String password, 密码-->而是数据库中存在的密码* Collection<? extends GrantedAuthority> authorities 当前用户具有的权限*/Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();//把List<Permission>转化为Collection<SimpleGrantedAuthority>for(Permission per:permissions){SimpleGrantedAuthority simpleGrantedAuthority=new SimpleGrantedAuthority(per.getPercode());authorities.add(simpleGrantedAuthority);}org.springframework.security.core.userdetails.User userDetail=new org.springframework.security.core.userdetails.User(user.getUsername(),user.getUserpwd(),authorities);return userDetail;}return null;}
}

第六步:创建Security配置文件   config层   mySecurityConfig文件

package com.aaa.config;import com.aaa.service.MyUserDetailService;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService userDetailService;//添加加密器@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//使用数据库账号和密码auth.userDetailsService(userDetailService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {//设置表单信息//使用自己的前端登录页面http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").successForwardUrl("/success").permitAll();//异常处理页面http.exceptionHandling().accessDeniedPage("/403.html");//禁用跨域伪造响应http.csrf().disable();//其他所有路径通过都需要认证http.authorizeRequests().anyRequest().authenticated();}
}

第七步:配置application.properties文件,连接数据库

server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/security
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root

第八步:在SpringSecurity002Application  启动类中添加注解让其扫描到com.aaa.dao层

package com;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
//添加注解  包扫描到dao层@MapperScan(basePackages = "com.aaa.dao")
public class SpringSecurity002Application {public static void main(String[] args) {SpringApplication.run(SpringSecurity002Application.class, args);}}

第九步:访问资源

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/8481.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【实战】CEF框架集成MFC DLL的一些坑

文章目录 DLL 导出方式&#xff0c;函数指针的坑问题出现问题解决 CEF集成MFCafxwin.h预编译编译参数修改 DLL重命名 MFC作为微软的长期主力开发套件之一&#xff0c;之前很多设备开发的C/S端界面都是通过MFC框架来做的&#xff0c;而在我自己的CEF项目中&#xff0c;会集成很多…

探索MacOS:苹果电脑的操作系统的魅力

引言&#xff1a; 当我们谈论优雅、简洁和高效的操作系统时&#xff0c;MacOS无疑是众多选择中的佼佼者。作为苹果电脑的专有操作系统&#xff0c;MacOS以其独特的用户界面、强大的性能和丰富的生态系统赢得了全球用户的喜爱。本文将带您深入了解MacOS的魅力所在&#xff0c;以…

QKD安全攻击防御方案分析和分级评估研究报告

今天分享的是行业报告&#xff1a;《QKD安全攻击防御方案分析和分级评估研究报告》 &#xff08;内容出品方&#xff1a;量子信息网络产业联盟&#xff09; 报告共计&#xff1a;180页 来源&#xff1a;《见鹿报告》 前言 量子通信是量子信息科学的重要分支&#xff0c;它…

嵌入式I2C 信号线为何加上拉电阻(图文并茂)

IIC 是一个两线串行通信总线&#xff0c;包含一个 SCL 信号和 SDA 信号&#xff0c;SCL 是时钟信号&#xff0c;从主设备发出&#xff0c;SDA 是数据信号&#xff0c;是一个双向的&#xff0c;设备发送数据和接收数据都是通过 SDA 信号。 在设计 IIC 信号电路的时候我们会在 SC…

C语言第二十四弹---指针(八)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、数组和指针笔试题解析 1.1、字符数组 1.1.1、代码1&#xff1a; 1.1.2、代码2&#xff1a; 1.1.3、代码3&#xff1a; 1.1.4、代码4&#xff1a; 1…

认识TypeScript 中的接口和类

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 接口 类 江城开朗的豌豆 在 TypeScript 中&…