SpringBoot安全管理之基于数据库认证的方法(springboot,数据库,开发技术)

时间:2024-04-27 16:37:28 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

这篇“SpringBoot安全管理之基于数据库认证的方法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot安全管理之基于数据库认证的方法”文章吧。

1. 设计数据表

用户表、角色表、用户角色关联表

SpringBoot安全管理之基于数据库认证的方法

建表语句

CREATETABLE`role`(`id`int(11)NOTNULL,`name`varchar(32)DEFAULTNULL,`nameZh`varchar(32)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;CREATETABLE`user`(`id`int(11)NOTNULL,`username`varchar(32)DEFAULTNULL,`password`varchar(255)DEFAULTNULL,`enabled`varchar(1)DEFAULTNULL,`locked`varchar(1)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;CREATETABLE`user_role`(`id`int(11)NOTNULL,`uid`int(11)DEFAULTNULL,`rid`int(11)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;

初始化数据

注意:角色名有一个默认的前缀 ROLE_

INSERTINTO`user`(`id`,`username`,`password`,`enabled`,`locked`)VALUES(1,'root','$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e','1','0');INSERTINTO`user`(`id`,`username`,`password`,`enabled`,`locked`)VALUES(2,'admin','$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e','1','0');INSERTINTO`user`(`id`,`username`,`password`,`enabled`,`locked`)VALUES(3,'tangsan','$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e','1','0');INSERTINTO`role`(`id`,`name`,`nameZh`)VALUES(1,'ROLE_dba','数据库管理员');INSERTINTO`role`(`id`,`name`,`nameZh`)VALUES(2,'ROLE_admin','系统管理员');INSERTINTO`role`(`id`,`name`,`nameZh`)VALUES(3,'ROLE_user','普通用户');INSERTINTO`user_role`(`id`,`uid`,`rid`)VALUES(1,1,1);INSERTINTO`user_role`(`id`,`uid`,`rid`)VALUES(2,1,2);INSERTINTO`user_role`(`id`,`uid`,`rid`)VALUES(3,2,2);INSERTINTO`user_role`(`id`,`uid`,`rid`)VALUES(4,3,3);

2. 创建项目

MyBatis 灵活,JPA 便利,此处选择前者,创建 Spring Boot Web 项目添加如下依赖:

<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>1.3.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency>

3. 配置数据库

在 application.properties 中进行数据连接配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/jpa

4. 创建实体类

Role

publicclassRole{privateIntegerid;privateStringname;privateStringnameZh;publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetNameZh(){returnnameZh;}publicvoidsetNameZh(StringnameZh){this.nameZh=nameZh;}}

User

publicclassUserimplementsUserDetails{privateIntegerid;privateStringusername;privateStringpassword;privateBooleanenabled;privateBooleanlocked;privateList<Role>roles;@OverridepublicCollection<?extendsGrantedAuthority>getAuthorities(){List<SimpleGrantedAuthority>authorities=newArrayList<>();for(Rolerole:roles){authorities.add(newSimpleGrantedAuthority(role.getName()));}returnauthorities;}@OverridepublicStringgetPassword(){returnpassword;}@OverridepublicStringgetUsername(){returnusername;}@OverridepublicbooleanisAccountNonExpired(){returntrue;}@OverridepublicbooleanisAccountNonLocked(){return!locked;}@OverridepublicbooleanisCredentialsNonExpired(){returntrue;}@OverridepublicbooleanisEnabled(){returnenabled;}publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}publicvoidsetUsername(Stringusername){this.username=username;}publicvoidsetPassword(Stringpassword){this.password=password;}publicBooleangetEnabled(){returnenabled;}publicvoidsetEnabled(Booleanenabled){this.enabled=enabled;}publicBooleangetLocked(){returnlocked;}publicvoidsetLocked(Booleanlocked){this.locked=locked;}publicList<Role>getRoles(){returnroles;}publicvoidsetRoles(List<Role>roles){this.roles=roles;}}

代码解释:

用户实体类需要实现 UserDetails 接口,并且实现该接口中的 7 个方法

| 方法名 | 解释 |

| &mdash; | &mdash; |

| getAuthorities() | 获取当前用户对象所具有的角色信息 |

| getPassword() | 获取当前用户对象的密码 |

| getUsername() | 获取当前用户对象的用户名 |

| isAccountNonExpired() | 当前账号是否未过期 |

| isAccountNonLocked() | 当前账号是否未锁定 |

| isCredentialsNonExpired() | 当前账号密码是否未过期 |

| isEnabled() | 当前账号是否可用 |

用户根据实际情况设置这 7 个方法的返回值。因为默认情况下不需要开发者自己进行密码角色等信息的比对,开发者只需要提供相关信息即可,例如 getPassword() 方法返回的密码和用户输入的密码不匹配,会自动抛出 BadCredentialsException 异常,isAccountNonExpired() 方法返回了 false ,会自动抛出 AccountExpiredException 异常,因此对开发者而言,只需要按照数据库中的数据在这里返回相应的配置即可。此处因为数据库中只有 enabled 和 locked 字段,故帐号未过期和密码未过期两个方法都返回 true

getAuthorities() 用来获取当前用户所具有的角色信息,此处用户所具有的角色存储在 roles 属性中,因此该方法直接遍历 roles 属性,然后构造 SimpleGrantedAuthority 集合并返回

5. 创建UserService

@ServicepublicclassUserServiceimplementsUserDetailsService{@AutowiredUserMapperuserMapper;@OverridepublicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{Useruser=userMapper.loadUserByUsername(username);if(user==null){thrownewUsernameNotFoundException("账户不存在!");}user.setRoles(userMapper.getUserRolesByUid(user.getId()));returnuser;}}

代码解释:

  • 定义 UserService 实现 UserDetailsService 接口,并实现该接口中的 loadUserByUsername 方法,该方法的参数就是用户登录时输入的用户名,通过用户名去数据库中查找用户,如果没有查询到用户,就抛出一个账号不存在的异常,如果查找到了用户,就继续查询该用户所具有的角色信息,并将获取到的 user 对象返回,再由系统提供的 DaoAuthenticationProvider 类去比对密码是否正确

  • loadUserByUsername 方法将在用户登录时自动调用

涉及到的 UserMapper 和 UserMapper.xml 如下

@MapperpublicinterfaceUserMapper{UserloadUserByUsername(Stringusername);List<Role>getUserRolesByUid(Integerid);}
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="org.sang.mapper.UserMapper"><selectid="loadUserByUsername"resultType="org.sang.model.User">select*fromuserwhereusername=#{username}</select><selectid="getUserRolesByUid"resultType="org.sang.model.Role">select*fromroler,user_roleurwherer.id=ur.ridandur.uid=#{id}</select></mapper>

6. 配置Spring Security

@ConfigurationpublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredUserServiceuserService;@BeanPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.userDetailsService(userService);}@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.authorizeRequests().antMatchers("/admin/**").hasRole("admin").antMatchers("/db/**").hasRole("dba").antMatchers("/user/**").hasRole("user").anyRequest().authenticated().and().formLogin().loginProcessingUrl("/login").permitAll().and().csrf().disable();}}

此处的配置与上篇介绍的一致,唯一不同的是没有配置内存用户,而是将刚刚创建好的 UserService 配置到 AuthenticationManagerBuilder 中。

7.创建Controller

@RestControllerpublicclassHelloController{@GetMapping("/admin/hello")publicStringadmin(){return"helloadmin";}@GetMapping("/db/hello")publicStringdba(){return"hellodba";}@GetMapping("/user/hello")publicStringuser(){return"hellouser";}}

8. 测试

登录 admin 用户,访问 /admin/hello,报了以下错误

Invalid bound statement (not found)

pom.xml 新增以下配置

<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory></resource></resources></build>

再次登录访问 /admin/hello,报了以下错误

Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Illegal overloaded getter method with ambiguous type for property enabled in class class org.sang.model.User. This breaks the JavaBeans specification and can cause unpredictable results.

去掉 User 实体类中 enabled 属性的 get set 方法,如下

publicclassUserimplementsUserDetails{privateIntegerid;privateStringusername;privateStringpassword;privateBooleanenabled;privateBooleanlocked;privateList<Role>roles;@OverridepublicCollection<?extendsGrantedAuthority>getAuthorities(){List<SimpleGrantedAuthority>authorities=newArrayList<>();for(Rolerole:roles){authorities.add(newSimpleGrantedAuthority(role.getName()));}returnauthorities;}@OverridepublicStringgetPassword(){returnpassword;}@OverridepublicStringgetUsername(){returnusername;}@OverridepublicbooleanisAccountNonExpired(){returntrue;}@OverridepublicbooleanisAccountNonLocked(){return!locked;}@OverridepublicbooleanisCredentialsNonExpired(){returntrue;}@OverridepublicbooleanisEnabled(){returnenabled;}publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}publicvoidsetUsername(Stringusername){this.username=username;}publicvoidsetPassword(Stringpassword){this.password=password;}publicBooleangetLocked(){returnlocked;}publicvoidsetLocked(Booleanlocked){this.locked=locked;}publicList<Role>getRoles(){returnroles;}publicvoidsetRoles(List<Role>roles){this.roles=roles;}}

再次登录访问 /admin/hello

SpringBoot安全管理之基于数据库认证的方法

访问 /db/hello

SpringBoot安全管理之基于数据库认证的方法

访问 /user/hello

SpringBoot安全管理之基于数据库认证的方法

以上就是关于“SpringBoot安全管理之基于数据库认证的方法”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

本文:SpringBoot安全管理之基于数据库认证的方法的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Python怎么使用plt.boxplot()函数绘制箱图下一篇:

8 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18