简介:

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

开始:

首先建表并且插入数据:

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. Android studio 报错Error:Internal error: (java.lang.ClassNotFoundException) com.google.wireless.android.sdk.stats.IntellijIndexingStats$Index

    Android studio运行make build报错 解决方法 在studio的File-->Settings-->Build, Execution, Deployment---> ...

  2. spring boot 的 userRepository无法注入的问题

    No qualifying bean of type 'xxx.xxx.xxx' available: expected at least 1 bean which qualifies as auto ...

  3. CTF中关于XXE(XML外部实体注入)题目两道

    题目:UNCTF-Do you like xml? 链接:http://112.74.37.15:8008/ hint:weak password (弱密码) 1.观察后下载图片拖进WINHEX发现提 ...

  4. java小心机(2)| 重载和构造器的小细节

    每天进步一点点,距离大腿又近一步! 阅读本文大概需要10分钟 java小心机,为你诉说java鲜为人知的一面 涉及基本数据类型的重载 基本类型能从一个"较小"的类型自动提升到&qu ...

  5. 大叔 Frameworks.Entity.Core 2 PageList

    Frameworks.Entity.Core\Commons\PageList\ 1 分页通用类 ListPageList<T> 继承  PageListBase<T>, IP ...

  6. 基于Bootstrap和Knockout.js的ASP.NET MVC开发实战 关于 拦截器的 学习 部分

    先贴一段: 下面贴代码: 上面这段代码呢,有几个点迷糊.可以找找看

  7. 使用luabind绑定box2d的lua接口

    最近在使用luabind绑定box2d的lua接口,发现不少问题.写在这里与大家分享. 1. body,fixture,joint的userdata.box2d的userdata的数据类型是void* ...

  8. Client API Object Model - Form Context

    FormContext 提供界面或者界面上控件的的引用. 比如说 quick view control, row in an editable grid 等等. Xrm.Page 和 getFormC ...

  9. [Java] The imoprt XXX cannot be resolved

    不知道为什么突然报错,但是可以成功编译. 通过import一个未使用的包来消除error,猜测是插件的问题,具体原因未知. import 未使用的包后,error消失.

  10. 关于 JavaSrcipt 前端开发的建议:模块化开发

    JavaScript 是一种优秀的脚本语言. 在 JavaScript 的诞生之初,便于 浏览器 密不可分,如今它更是到了服务器中大展身手. 但是这里不叙述服务端的开发建议. Script 翻译过来就 ...