Spring Boot Security 保护你的程序
Spring Boot Security
本示例要内容
- 基于角色的权限访问控制
- 加密、解密
- 基于Spring Boot Security 权限管理框架保护应用程序
String Security介绍
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
快速上手
1.创建表
CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user_role` (
`user_id` bigint(11) NOT NULL,
`role_id` bigint(11) NOT NULL
);
CREATE TABLE `role_permission` (
`role_id` bigint(11) NOT NULL,
`permission_id` bigint(11) NOT NULL
);
CREATE TABLE `permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NULL,
`pid` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
);
2.添加maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-security4</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
3.配置文件
spring:
thymeleaf:
encoding: UTF-8
cache: false
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/easy_web?useSSL=false&serverTimezone=UTC
username: root
password: 123456
4.自定义UserDetailsService,实现用户登录功能
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleMapper roleMapper;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
//查数据库
User user = userMapper.loadUserByUsername(userName);
if (null != user) {
List<Role> roles = roleMapper.getRolesByUserId(user.getId());
user.setAuthorities(roles);
}
return user;
}
}
5.资源初始化
@Component
@Slf4j
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {
@Autowired
private PermissionMapper permissionMapper;
/**
* 每一个资源所需要的角色 Collection<ConfigAttribute>决策器会用到
*/
private static HashMap<String, Collection<ConfigAttribute>> map = null;
/**
* 返回请求的资源需要的角色
*/
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
//object 中包含用户请求的request 信息
HttpServletRequest request = ((FilterInvocation) o).getHttpRequest();
for (Iterator<String> it = map.keySet().iterator(); it.hasNext(); ) {
String url = it.next();
log.info("url==>{},request==>{}", url, request.getRequestURI());
if (new AntPathRequestMatcher(url).matches(request)) {
return map.get(url);
}
}
return new ArrayList<>();
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
//初始化 所有资源 对应的角色
loadResourceDefine();
return new ArrayList<>();
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
/**
* 初始化 所有资源 对应的角色
*/
public void loadResourceDefine() {
map = new HashMap<>(16);
//权限资源 和 角色对应的表 也就是 角色权限 中间表
List<RolePermisson> rolePermissons = permissionMapper.getRolePermissions();
//某个资源 可以被哪些角色访问
for (RolePermisson rolePermisson : rolePermissons) {
String url = rolePermisson.getUrl();
String roleName = rolePermisson.getRoleName();
ConfigAttribute role = new SecurityConfig(roleName);
if (map.containsKey(url)) {
map.get(url).add(role);
} else {
List<ConfigAttribute> list = new ArrayList<>();
list.add(role);
map.put(url, list);
}
}
}
}
6.决策器(也就是授权代码)
/**
* 决策器
*/
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
/**
* 通过传递的参数来决定用户是否有访问对应受保护对象的权限
*
* @param authentication 包含了当前的用户信息,包括拥有的权限。这里的权限来源就是前面登录时UserDetailsService中设置的authorities。
* @param object 就是FilterInvocation对象,可以得到request等web资源
* @param configAttributes configAttributes是本次访问需要的权限
*/
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if (null == configAttributes || 0 >= configAttributes.size()) {
return;
} else {
String needRole;
for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
needRole = iter.next().getAttribute();
for(GrantedAuthority ga : authentication.getAuthorities()) {
if(needRole.trim().equals(ga.getAuthority().trim())) {
return;
}
}
}
throw new AccessDeniedException("当前访问没有权限");
}
}
/**
* 表示此AccessDecisionManager是否能够处理传递的ConfigAttribute呈现的授权请求
*/
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
/**
* 表示当前AccessDecisionManager实现是否能够为指定的安全对象(方法调用或Web请求)提供访问控制决策
*/
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
7.最后一步Security配置
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService userService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//校验用户
auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
//对密码进行加密
@Override
public String encode(CharSequence charSequence) {
log.info(charSequence.toString());
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
}
//对密码进行判断匹配
@Override
public boolean matches(CharSequence charSequence, String s) {
String encode = DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
boolean res = s.equals(encode);
return res;
}
});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "index", "/login", "/login-error", "/401", "/css/**", "/js/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").failureUrl("/login-error")
.and()
.exceptionHandling().accessDeniedPage("/401");
http.logout().logoutSuccessUrl("/");
}
}
8.编写个控件器测试user用户和admin用户权限
@Controller
public class MainController {
@RequestMapping("/")
public String root() {
return "redirect:/index";
}
@RequestMapping("/index")
public String index() {
return "index";
}
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/login-error")
public String loginError(Model model) {
model.addAttribute("loginError", true);
return "login";
}
@GetMapping("/401")
public String accessDenied() {
return "401";
}
@GetMapping("/user/common")
public String common() {
return "user/common";
}
@GetMapping("/user/admin")
public String admin() {
return "user/admin";
}
}
资料
Spring Boot Security 保护你的程序的更多相关文章
- Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器
概要 之前的两篇文章,讲述了Spring Security 结合 OAuth2 .JWT 的使用,这一节要求对 OAuth2.JWT 有了解,若不清楚,先移步到下面两篇提前了解下. Spring Bo ...
- Spring Boot Security 整合 JWT 实现 无状态的分布式API接口
简介 JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案.JSON Web Token 入门教程 - 阮一峰,这篇文章可以帮你了解JWT的概念.本文重点讲解Spring Boo ...
- Spring Boot Security 整合 OAuth2 设计安全API接口服务
简介 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版.本文重点讲解Spring Boot项目对OAuth2进行的实现,如果你对OAut ...
- Spring Boot Security配置教程
1.简介 在本文中,我们将了解Spring Boot对spring Security的支持. 简而言之,我们将专注于默认Security配置以及如何在需要时禁用或自定义它. 2.默认Security设 ...
- Spring Boot Security Oauth2之客户端模式及密码模式实现
Spring Boot Security Oauth2之客户端模式及密码模式实现 示例主要内容 1.多认证模式(密码模式.客户端模式) 2.token存到redis支持 3.资源保护 4.密码模式用户 ...
- boke练习: spring boot: security post数据时,要么关闭crst,要么添加隐藏域
spring boot: security post数据时,要么关闭crst,要么添加隐藏域 http.csrf().disable(); 或者: <input name="${_cs ...
- Spring Boot Security And JSON Web Token
Spring Boot Security And JSON Web Token 说明 流程说明 何时生成和使用jwt,其实我们主要是token更有意义并携带一些信息 https://github.co ...
- Spring Boot Security 使用教程
虽然,我在实际项目中使用的是 shiro 进行权限管理,但 spring boot security 早已大名鼎鼎,虽然他的入门要相对复杂一点,但是设计视乎更加吸引人. 本章节就是以一篇快速入门 sp ...
- Spring Boot Security JWT 整合实现前后端分离认证示例
前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...
随机推荐
- 解决Connection to Xxx@localhost failed.
解决: Connection to jianshu@localhost failed. [08001] Could not create connection to database server. ...
- 微信小程序——template详细使用
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用减少冗余代码. 1.1定义模板 1.1.1.创建模板文件夹 1.1.2.使用 name 属性,作为模板的名字.然后 ...
- Anticancer Effect of Deuterium Depleted Water - Redox Disbalance Leads to Oxidative Stress(低氘水的抗癌作用-氧化还原失衡导致了氧化应激)-解读人:范徉
期刊名:Molecular & Cellular Proteomics 发表时间:(2019年12月) IF:4.828 单位:瑞典卡罗林斯卡学院 物种:人 技术:标记定量蛋白质组学,氧化还原 ...
- 关于Python的随机数模块,你必须要掌握!
所谓七夕 前几天的文章这个七夕节,用Python为女友绘制一张爱心照片墙吧!收获了最近以来最高的浏览量,没枉费我熬到夜里3点赶出来的热点文章.有付出就总会有所回报,只是看这天来的早晚而已.七夕一个人看 ...
- 详细nginx配置SSL
1.nginx的ssl 让nginx实现用https来访问网站,http是80端口,https是443端口. https其实就是一种加密的http 2.为什么要加密 例子:在网上银行汇款,在你汇款的过 ...
- golang数据结构之总结
golang语言的一些数据结构实现,包括: 队列(单队列.循环队列) 链表(单链表.双链表.循环链表(解决约瑟夫环问题)) 栈(实现加减乘除计算) 递归之迷宫问题 哈希表(员工管理系统) 树(三种遍历 ...
- RabbitMQ的三大交换器
pom文件都是相同的 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- HDU1885 Key Task
The Czech Technical University is rather old — you already know that it celebrates 300 years of its ...
- spring security 权限安全认证框架-入门(一)
spring security 概述: Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架.它是保护基于spring的应用程序的实际标准. Spring Security ...
- 第一节:Shiro HelloWorld 实现
1.新建maven工程,pom配置maven jar包 <dependency> <groupId>org.apache.shiro</groupId> <a ...