简介:

  上篇文章向读者介绍的认证数据都是定义在内存中的,在真实项目中,用户的基本信息以及角色等都存储在数据库中,因此需要从数据库中获取数据进行认证。

开始:

首先建表并且插入数据:

pom.xml

   <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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

创建实体类:

public class User implements UserDetails {
private Integer id;
private String username;
private String password;
private Boolean enabled;
private Boolean locked;
private List<Role> roles;
  
//获取当前用户对象所具有的所有角色信息
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
return authorities;
}
//获取当前对象密码
@Override
public String getPassword() {
return password;
}
//获取当前对象用户名
@Override
public String getUsername() {
return username;
}
//判断账户是否过期
@Override
public boolean isAccountNonExpired() {
return true;
}
//判断账户是否被锁
@Override
public boolean isAccountNonLocked() {
return !locked;
}
//当前账户密码是否过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
//判断当前账户是否可用
@Override
public boolean isEnabled() {
return enabled;
}
//省略getter/setter }
public class Role {
private Integer id;
private String name;
private String nameZh;
//省略getter/setter }

Service:

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

@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("账户不存在!");
}
user.setRoles(userMapper.getUserRolesByUid(user.getId()));
return user;
}
}

Mapper:

@Mapper
public interface UserMapper {
User loadUserByUsername(String username);
List<Role> getUserRolesByUid(Integer id);
}
<mapper namespace="org.sang.security02.mapper.UserMapper">
<select id="loadUserByUsername" resultType="org.sang.security02.model.User">
select * from user where username=#{username}
</select>
<select id="getUserRolesByUid" resultType="org.sang.security02.model.Role">
select * from role r,user_role ur where r.id=ur.rid and ur.uid=#{id}
</select>
</mapper>

配置SpringSecurity

角色继承:

 在上面定义了三种角色,但是这三种角色之间不具备任何关系,一般来说角色之间是有关系的,例如ROLE admin -般既具有admin的权限,又具有user的权限。那么如何配置

这种角色继承关系呢?在Spring Security 中只需要开发者提供一-个RoleHierarchy即可。

  以上面的案例为例,假设ROLE_dba是终极大Boss,具有所有的权限,ROLE_admin具有ROLE _user 的权限,ROL_user 则是一个公共角色,即ROLE_admin继承ROLE_user、 ROLE_dba继承ROLE_ admin, 要描述这种继承关系,只需要开发者在Spring Security 的配置类中提供一个RoleHierarchy即可,代码如下:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Bean
RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ROLE_dba > ROLE_admin ROLE_admin > ROLE_user";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);      //没有将用户存在内存中,而是从数据库中取出来
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setSecurityMetadataSource(cfisms());
object.setAccessDecisionManager(cadm());
return object;
}
})
.and()
.formLogin()
.loginProcessingUrl("/login").permitAll()
.and()
.csrf().disable();
}
@Bean
CustomFilterInvocationSecurityMetadataSource cfisms() {
return new CustomFilterInvocationSecurityMetadataSource();
}
@Bean
CustomAccessDecisionManager cadm() {
return new CustomAccessDecisionManager();
}
}

Controller:

@RestController
public class HelloController {
@GetMapping("/admin/hello")
public String admin() {
return "hello admin";
}
@GetMapping("/db/hello")
public String dba() {
return "hello dba";
}
@GetMapping("/user/hello")
public String user() {
return "hello user";
}
}

SpringBoot安全管理--(二)基于数据库的认证的更多相关文章

  1. Cas(06)——基于数据库的认证

    基于数据库的认证 目录 1.1      BindModeSearchDatabaseAuthenticationHandler 1.2      QueryDatabaseAuthenticatio ...

  2. Ecside基于数据库的过滤、分页、排序

    首先ecside展现列表.排序.过滤(该三种操作以下简称为 RSF )的实现原理完全和原版EC一样, 如果您对原版EC的retrieveRowsCallback.sortRowsCallback.fi ...

  3. ASP.NET Core 基于JWT的认证(二)

    ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...

  4. 基于Springboot集成security、oauth2实现认证鉴权、资源管理

    1.Oauth2简介 OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAu ...

  5. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例

    1.前言 本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管理系统实例. 使用技术:SpringBoot.mybatis.shiro.thymeleaf.pagehelp ...

  6. 使用SSM 或者 springboot +mybatis时,对数据库的认证信息(用户名,密码)进行加密。

    通常情况下,为了提高安全性,我们需要对数据库的认证信息进行加密操作,然后在启动项目的时候,会自动解密来核对信息是否正确.下面介绍在SSM和springboot项目中分别是怎样实现的. 无论是使用SSM ...

  7. spring security基于数据库表进行认证

    我们从研究org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl.class的源码开始 public class JdbcDaoI ...

  8. SpringBoot基于数据库实现简单的分布式锁

    本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...

  9. SpringBoot基于数据库的定时任务实现

    在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现. 基于注解来创建定时任务非常简单,只需几行代码便可完成.实现如下: @Configur ...

随机推荐

  1. 进击.net 三大框架

    spring mybatis NHibernate

  2. VMware 虚拟机开机黑屏

    先记录一下害我差点点就又跑去重装了 好几天未打开vm 打开就黑屏 打开虚拟机就是黑屏没反应 找了很久(好像是wegame的原因,昨晚上好像是打开了wegame更新2k和lol) 1献上解决方案 管理员 ...

  3. Nginx code 状态码说明

    最近了解下Nginx的Code状态码,在此简单总结下. 先来再回顾一下一个http请求处理流程: 一个普通的http请求处理流程,如上图所示: A -> client端发起请求给nginx B ...

  4. HDFS NameNode重启优化

    http://tech.meituan.com/namenode-restart-optimization.html 一.背景 在Hadoop集群整个生命周期里,由于调整参数.Patch.升级等多种场 ...

  5. innobackupex 恢复脚本

    此脚本需要与我前几天写的备份脚本配套才能使用 这里也对innobackupex吐槽下,当使用innobackupex进行恢复的时候,必须要清除所有原数据文件,但是一旦恢复失败,则连实例都将丢失,不成功 ...

  6. C++快读模板

    C++的快速读入模板 inline int read() { ; char ch = getchar(); ') { if (ch == '-') flag = true; ch = getchar( ...

  7. 【vue_django】成功登录后,保存用户

    PS:使用session 保存: // 登录 login() { if (this.username === "" || this.password === "" ...

  8. Unreal Engine 4 蓝图完全学习教程(一)—— 简要介绍

    首先启动UE4: 新建项目类型为游戏: 选择空项目Blank: 项目设置选项: 点击创建项目: 打开后的窗口称为:“关卡编辑器”,由多个面板组成.在UE中,设计3D场景的空间称为“关卡”. 简单介绍一 ...

  9. POJ_1006_中国剩余

    http://poj.org/problem?id=1006 中国剩余定理用来解求模方程组,用到了逆元. 这题三个数互质,直接用扩展欧几里德可得逆元. #include<iostream> ...

  10. CCF_ 201312-2_ISBN号码

    水. #include<cstdio>#include<string>#include<iostream>using namespace std; int main ...