SpringSecurity基于数据库认证

Posted 鼓捣猫腻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringSecurity基于数据库认证相关的知识,希望对你有一定的参考价值。

一、创建项目并导入相关依赖

   

<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>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.1.1</version>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid-spring-boot-starter</artifactId>

<version>1.1.10</version>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

<version>5.1.27</version>

</dependency>

   

   

   

注:maven默认不编译src/main/java下的xml文件,需要我们手动导入

   

二、相关配置和代码

   

1)application.properties

   

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/security

spring.datasource.username=root

spring.datasource.password=123

   

2)数据库脚本

   

/*

  

  

Navicat MySQL Data Transfer

  

Source Server : localhost

  

Source Server Version : 50717

  

Source Host : localhost:3306

  

Source Database : security

  

Target Server Type : MYSQL

  

Target Server Version : 50717

  

File Encoding : 65001

  

Date: 2018-07-28 15:26:51

  

*/

  

SET FOREIGN_KEY_CHECKS=0;

  

-- ----------------------------

  

-- Table structure for role

  

-- ----------------------------

  

DROP TABLE IF EXISTS `role`;

  

CREATE TABLE `role` (

  

`id` int(11) NOT NULL AUTO_INCREMENT,

  

`name` varchar(32) DEFAULT NULL,

  

`nameZh` varchar(32) DEFAULT NULL,

  

PRIMARY KEY (`id`)

  

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

  

-- ----------------------------

  

-- Records of role

  

-- ----------------------------

  

INSERT INTO `role` VALUES (\'1\', \'ROLE_dba\', \'数据库管理员\');

  

INSERT INTO `role` VALUES (\'2\', \'ROLE_admin\', \'系统管理员\');

  

INSERT INTO `role` VALUES (\'3\', \'ROLE_user\', \'用户\');

  

-- ----------------------------

  

-- Table structure for user

  

-- ----------------------------

  

DROP TABLE IF EXISTS `user`;

  

CREATE TABLE `user` (

  

`id` int(11) NOT NULL AUTO_INCREMENT,

  

`username` varchar(32) DEFAULT NULL,

  

`password` varchar(255) DEFAULT NULL,

  

`enabled` tinyint(1) DEFAULT NULL,

  

`locked` tinyint(1) DEFAULT NULL,

  

PRIMARY KEY (`id`)

  

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

  

-- ----------------------------

  

-- Records of user

  

-- ----------------------------

  

INSERT INTO `user` VALUES (\'1\', \'root\', \'$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq\', \'1\', \'0\');

  

INSERT INTO `user` VALUES (\'2\', \'admin\', \'$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq\', \'1\', \'0\');

  

INSERT INTO `user` VALUES (\'3\', \'sang\', \'$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq\', \'1\', \'0\');

  

-- ----------------------------

  

-- Table structure for user_role

  

-- ----------------------------

  

DROP TABLE IF EXISTS `user_role`;

  

CREATE TABLE `user_role` (

  

`id` int(11) NOT NULL AUTO_INCREMENT,

  

`uid` int(11) DEFAULT NULL,

  

`rid` int(11) DEFAULT NULL,

  

PRIMARY KEY (`id`)

  

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

  

-- ----------------------------

  

-- Records of user_role

  

-- ----------------------------

  

INSERT INTO `user_role` VALUES (\'1\', \'1\', \'1\');

  

INSERT INTO `user_role` VALUES (\'2\', \'1\', \'2\');

  

INSERT INTO `user_role` VALUES (\'3\', \'2\', \'2\');

  

INSERT INTO `user_role` VALUES (\'4\', \'3\', \'3\');

  

SET FOREIGN_KEY_CHECKS=1;

   

   

3)数据库结构

   

   

   

   

   

密码是123 springsecurity加密算法后的密文,可以让同样的密码每次生成的密文都不一样,从而不会重复,我们案列中的密文是我偷懒复制粘贴的所以一样

   

也就是该类完成加密的

   

   

4)创建实体类User,Role

   

4.1)创建User实现UserDetails

   

   

这里要实现UserDetails接口,这个接口好比一个规范。防止开发者定义的密码变量名各不相同,从而导致springSecurity不知道哪个方法是你的密码

   

我给的数据库中user表没有UserDetails的几个方法,可以直接手动给它true

   

   

有的就是用数据库查出来的属性

   

   

   

4.2)创建Role类

   

   

5)创建UserMapper和UserMapper.xml

   

5.1)UserMapper.class

   

注:以前在SSM框架之所以不用加类似@Service和@controller的注解时因为我们在xml文件已经配置了,如今使用SpringBoot所以我们也要改变写法

   

一共两种写法

   

5.1.1)在类上直接加@Mapper

   

   

5.1.2)在SpringBoot启动类上配置全局的扫描

   

   

5.2)UserMapper.xml

   

   

   

   

   

6)创建UserService类

   

6.1)UserService同样也要继承UserServiceDetails接口

   

   

   

   

7)创建SercurityConfig配置类

   

   

7.1)SercurityConfig需要继承WebSecurityConfigurerAdapter类,并在类上加@configuration

   

   

   

7.2)SpringSecurity5.0之后密码必须加密

   

   

7.3)把数据库查出的用户信息交给SpringSecurity处理

   

   

这样就算完成了一半了,为什么说完成一半因为这些并不是全部代码下半部分我下篇博客写,这样比较容易接受,所以url的权限还是写死的

  下篇博客https://www.cnblogs.com/fernfei/p/12194847.html

7.4)配置httpSercurity

   

   

下图的代码可以参考我另一个博客介绍里面有这段全部代码,并有解释

https://www.cnblogs.com/fernfei/p/12185186.html

   

   

这里解释一下为什么数据库中的user表需要加ROLE_这样前缀,可以看一下源码

①处告诉我们如果在.antMatchers("/dba/**").hasRole("dba")的时候加前缀会抛异常

   

②处告诉我们为什么在.antMatchers("/dba/**").hasRole("dba")的时候不需要加ROLE_前缀

   

   

   

   

8)角色继承

   

8.1)在Spring Boot2.0.8(含)版本的时候是以下写法

   

用空格把ROLE_dba>ROLE_admin ROLE_admin>ROLE_user分开

   

@Bean

RoleHierarchyroleHierarchy(){

   

RoleHierarchyImplroleHierarchy=newRoleHierarchyImpl();

Stringhierarchy="ROLE_dba>ROLE_adminROLE_admin>ROLE_user";

roleHierarchy.setHierarchy(hierarchy);

returnroleHierarchy;

}

   

8.2)Spring Boot2.0.8(不含)之后得版本用 \\n 来区分

   

@Bean

RoleHierarchyroleHierarchy(){

   

RoleHierarchyImplroleHierarchy=newRoleHierarchyImpl();

Stringhierarchy="ROLE_dba>ROLE_admin\\nROLE_admin>ROLE_user";

roleHierarchy.setHierarchy(hierarchy);

returnroleHierarchy;

}

   

   

9)方法安全

   

9.1)在SecurityConfig配置上类加上

   

@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true)

   

   

   

9.2)在Service层创建一个MethodService,当然并一定非要叫这个类名 可以根据你的具体业务考虑加在哪里

   

   

10)controller层

   

以上是关于SpringSecurity基于数据库认证的主要内容,如果未能解决你的问题,请参考以下文章

六SpringSecurity Web权限方案—— 基于数据库实现权限认证

六SpringSecurity Web权限方案—— 基于数据库实现权限认证

SpringSecurity实现前后端分离项目的登录认证

万字长文 基于SpringBoot整合SpringSecurity的认证授权(角色+权限) 真案列有数据库有源码

前后端分离项目 — 基于SpringSecurity OAuth2.0用户认证

SpringSecurity认证流程分析