前言:

利用数据库视图,实现web接口查询敏感信息时动态脱敏。

具体目标:某接口为用户信息查询接口,返回敏感用户信息(id,姓名、手机号【敏感】、身份证号【敏感】),如果web用户为管理员角色,则查询后返回明文用户信息,如果用户为普通用户信息,则查询后返回脱敏后的用户信息。

具体步骤:

一、在mysql中新建一个用户信息表,并添加几条数据

二、对上表创建脱敏后的视图,利用掩码技术脱敏,脱敏字段为phone和id_card

create view  user_info_view as select id,name,concat(left(phone,3),'****',right(phone,3)) as phone,concat(left(id_card,4),'**************') as id_card from user_info;

三、SpringBoot项目启用SpringSecurity,在配置文件中,内存新建账号的时候添加admin和normal两个角色

package Eleven.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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("123456")).roles("admin");
auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("123456")).roles("normal");
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 定义哪些URL需要被保护、哪些不需要被保护
.antMatchers("/login").permitAll()// 设置所有人都可以访问登录页面
.anyRequest().authenticated() // 任何请求,登录后可以访问
.and()
.formLogin().loginPage("/login")
; }
}

四、创建UserInfo的domain类

package Eleven.domain;

public class UserInfo {

    private long id;
private String name;
private String phone;
private String id_card; public long getId() {
return id;
} public void setId(long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
} public String getId_card() {
return id_card;
} public void setId_card(String id_card) {
this.id_card = id_card;
}
}

五、创建Mapper,访问数据库的接口,两个查询方法,以便按不同的角色区分查询原始表还是脱敏后的视图

package Eleven.mapper;

import Eleven.domain.UserInfo;
import org.apache.ibatis.annotations.*; @Mapper
public interface UserMapper { //根据用户名查询,查询原始表,明文显示敏感信息
@Select("select * from user_info where name=#{name}")
UserInfo findByName(String name); //根据用户名查询,查询脱敏后的视图表,脱敏显示敏感信息
@Select("select * from user_info_view where name=#{name}")
UserInfo findByNameSec(String name);
}

六、创建Service 和Impl文件

package Eleven.service;

import Eleven.domain.UserInfo;

public interface UserService {

    public UserInfo find(String name);

    public UserInfo findSec(String name);

}
package Eleven.impl;

import Eleven.domain.UserInfo;
import Eleven.mapper.UserMapper;
import Eleven.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper; @Override
public UserInfo find(String name){
return userMapper.findByName(name);
} public UserInfo findSec(String name){
return userMapper.findByNameSec(name);
}
}

七、创建controller文件,其中Get请求中,获取登录用户的角色,不同的角色调用Service中不同的函数,最终admin用户在数据库原始表中执行SQL查询,普通用户在脱敏后的视图中执行SQL查询

package Eleven.controller;

import Eleven.domain.User;
import Eleven.domain.UserInfo;
import Eleven.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class UserController {
@Autowired
private UserService userService; @GetMapping("/findByName")
public Object findByName(String name){
/**
* 获取登录用户的角色,不同角色调用Service中不同的函数,最终执行不同的Sql查询
*/
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth.getAuthorities().toString().equals("[ROLE_admin]")){
UserInfo userInfo = userService.find(name);
return userInfo;
}
else if (auth.getAuthorities().toString().equals("[ROLE_normal]")){
UserInfo userInfo = userService.findSec(name);
return userInfo;
}
else {
return auth.getAuthorities().toString();
} } }

八、测试验证

1、访问SpringBoot WEB,进入登录页面

2、使用admin用户登录后,访问查询用户信息接口,如下图所示,返回的是明文用户信息

3、使用user普通用户登录后访问,如下图所示,返回的是脱敏后的用户信息

利用数据库视图技术实现动态脱敏,适用于web应用,适用于生产环境,可按用户角色返回脱敏前后的查询结果。但是所有敏感数据表均需生成视图,额外占用数据库存储空间;为了实现目标,研发人员需要额外的开发工作量。

最新文章

  1. [C#] 简单的 Helper 封装 -- CookieHelper
  2. 耿丹CS16-2班第五次作业汇总
  3. jQuery漂亮图标的垂直导航菜单
  4. MIFARE系列6《射频卡与读写器的通讯》
  5. busybox filesystem httpd php-5.5.31 sqlite3 webserver
  6. 去除Coding4Fun中MessagePrompt的边框(Border)
  7. jQuery滚动条插件 – jquery.slimscroll.js
  8. BZOJ 1642: [Usaco2007 Nov]Milking Time 挤奶时间
  9. 推翻自己和过往,重学自定义View
  10. StrutsPreparedAndExcuteFilter与Interceptor
  11. PyV8
  12. linux_熟悉常用Linux命令
  13. 仿stl+函数模板
  14. 以超级管理员方式运行bat文件
  15. 使用命令行编译QT helloworld 项目
  16. Oracle学习笔记:外连接(+)的用法
  17. Cassandra 和 Spark 数据处理一窥
  18. #2009. 「SCOI2015」小凸玩密室
  19. Task 6.1 校友聊之NABCD模型分析
  20. redis tutorail

热门文章

  1. jenkins配置publish over ssh遇到的问题
  2. 大话设计模式Python实现-职责链模式
  3. MySQL基础之STRAIGHT JOIN用法简介
  4. JDBC释放数据库连接
  5. WPF 使用SetParent嵌套窗口
  6. Sql 代码规范说明
  7. 基础面试,为什么面试官总喜欢问String?
  8. 部署asp.net core Kestrel 支持https 使用openssl自签ssl证书
  9. 【语义分割】Stacked Hourglass Networks 以及 PyTorch 实现
  10. python爬虫:将数据保存到本地