SpringBoot权限认证

SpringBoot的安全

常用框架:Shrio,SpringSecurity

两个功能:

  • Authentication 认证
  • Authorization 授权

权限:

  • 功能权限
  • 访问权限
  • 菜单权限

原来用拦截器、过滤器来做,代码较多。现在用框架。

SpringSecurity

只要引入就可以使用

可以在官网看教程

几个重要的类:

  • WebSecurityConfigurerAdapter 自定义Security策略
  • AuthenticationManagerBuilder 自定义认证策略
  • @EnableWebSercurity

基本操作

springboot 2.7.0前

继承WebSecurityConfigurerAdapter

重写configure(HttpSecurity http)方法——授权

使用链式编程

第一个小例子:

http.authorizeRequests()							//自定义权限控制
    .antMatchers("/").permitAll()					//所有人可以访问首页
    .addMatchers("/vip1").hasRole("vip1");			//vip1可以访问
//登录,也可以使用and()拼接
http.fromLogin();									//没有权限会自动跳转到登录页面,即使没有写过/login

源码:默认的login和login?error

重写Configure(AuthenticationManagerBuilder auth)方法——认证

2.7.0版本后,WebSecurityConfigurerAdapter被弃用

上面配置好了什么权限可以做什么事情,这里则用来做登录控制和权限查询操作

protected void configure(AuthenticationManagerBuilder auth){
    //因为反编译,新版要求所有密码必须加密
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //JDBC认证	例子为blog_system
    auth.jdbcAuthentication().passwordEncoder(encoder)
                .dataSource(dataSource)
                .usersByUsernameQuery(userSQL)				//通过username、password、enabled登录控制
                .authoritiesByUsernameQuery(authoritySQL);		//通过用户名、权限(在查询的第二列)获取role
    //内存认证	例子来自狂神说课堂笔记,没用数据库的例子
    auth.inMemoryAuthentication().passwordEncoder(encoder)								
        .withUSer("name").password( new BCryptPasswordEncoder("123456")).roles("vip2","vip3")
        .and()	//通过and拼接其他用户
        .withUSer("name2").password(new BCryptPasswordEncoder("123456")).roles("vip2","vip3");
    
    //自定义认证规则,接受Service参数	例子来自VBlog
    auth.userDetailsService(userService);
}

上面的最后一种方式:UserService继承UserDetailService,并重写方法

@Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(s);
        if (user == null) {
            //避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败
            return new User();
        }
        //查询用户的角色信息,并返回存入user中
        List<Role> roles = rolesMapper.getRolesByUid(user.getId());
        user.setRoles(roles);					
        return user;
    }

登录之后若没权限,就是跳转到没权限界面了

基于方法的动态权限

将用户的权限保存在数据库中,并实现动态权限控制。

在配置类上使用@EnableGlobalMethodSecurity来开启它;

然后在方法中使用@PreAuthorize配置访问接口需要的权限;

@PreAuthorize("hasAuthority('pms:product:create')")

权限字符串自定。
再从数据库中查询出用户所拥有的权限值设置到UserDetails对象中去。

ruoyi项目使用了这种方法

缺点:方法权限写死在代买里了,不好维护。也可以通过过滤器、拦截器实现,

@Since 2.7.0 新用法

新用法非常简单,无需再继承WebSecurityConfigurerAdapter,只需直接声明配置类,再配置一个生成SecurityFilterChainBean的方法,把原来的HttpSecurity配置移动到该方法中即可。

/**
 * SpringSecurity 5.4.x以上新用法配置
 * 为避免循环依赖,仅用于配置HttpSecurity
 * Created by macro on 2022/5/19.
 */
@Configuration
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        //省略HttpSecurity的配置
        return httpSecurity.build();
    }

}
Security上下文
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
注销

前端请求/logout

http.logout();
//会请求/logout,可以自定义url。默认回到/login?logout
//看源码,可以清空cookies和session
http.logout().logoutUrl("/")	//注销成功回首页
    .csrf().disable()			//关闭防止csrf攻击	csrf:跨站请求攻击,可能屏蔽get。

模板引擎相关功能

页面定制

登录:loginPage(“”),改完之后默认的login就没有了

点进去看源码

/*
.formLogin(formLogin ->
	 * 				formLogin
	 * 					.usernameParameter( username )			//默认
	 * 					.passwordParameter( password )
	 * 					.loginPage( /authentication/login )		登录路由
	 * 					.failureUrl(/authentication/login?failed)
	 * 					.loginProcessingUrl( /authentication/login/process )	登陆验证页面
	 * 			);
*/
“记住我”功能
http.rememberMe();	//登录页会有“记住我”	保存cookie	默认14天

Shiro

Apache 开源框架

三大对象:

  • Subject 用户
  • SecurityManager 管理用户
  • Realm 连接数据

Subject:主体,代表了当前 “用户”,与当前应用交互的任何东西都是 Subject,如网络爬虫,人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;

SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;

Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。

也就是说对于我们而言,最简单的一个 Shiro 应用:

  1. 应用代码通过 Subject 来进行认证和授权,而 Subject 又委托给 SecurityManager;
  2. 我们需要给 Shiro 的 SecurityManager 注入 Realm,从而让 SecurityManager 能得到合法的用户及其权限进行判断。
    <!--shiro依赖- SSM-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.4</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.2.4</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.2.4</version>
    </dependency>

image-20210303064855164
shiro-web提供了Web集成的支持,其通过一个 ShiroFilter 入口来拦截需要安全控制的 URL,然后进行相应的控制

1.编写配置类

@Configuration
public class ShiroConfig{
    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean hetShiroFilterFactoryBean(@Qualifier DefaultWebSercurityManager defaultWebSercurityManager){
 	ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defau+ltWebSercurityManager);
        Map<String,String> filterMap = new LinkedHashMap<>();
        
        filterMap.put("","authc")
        return bean;
    }
    
    //DefaultWebSercurityManager
    @Bean
    public DefaultWebSercurityManager getDefaultWebSercurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSercurityManager sercurityManager new DefaultWebSercurityManager();
        securityManager.setRealm(userRealm);
        return sercurityManager;
    }
    
    //Realm	自定义
    @Bean
    public Realm userRealm(){
        return new UserRealm();
    }
}
public UserRealm extends AuthorizingRealm{
    
   	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// 用户名
		String username = (String) token.getPrincipal();
		// 密码
		String password = new String((char[]) token.getCredentials());
		Userlogin userlogin = null;
		try {
			userlogin = userloginService.findByName(username);
		} catch (Exception e) {
			e.printStackTrace();
		}
        
		if (userlogin == null) {
			// 没有该用户名
			throw new UnknownAccountException();
		} else if (!password.equals(userlogin.getPassword())) {
			// 密码错误
			throw new IncorrectCredentialsException();
		}
		// 身份验证通过,返回一个身份信息
		AuthenticationInfo aInfo = new SimpleAuthenticationInfo(username, password, getName());

		return aInfo;
	}
}

2.登录控制

//登录表单处理
    @RequestMapping(value = "/login", method = {RequestMethod.POST})
    public String login(Userlogin userlogin) throws Exception {

        //Shiro实现登录
        UsernamePasswordToken token = new UsernamePasswordToken(userlogin.getUsername(),
                userlogin.getPassword());
        Subject subject = SecurityUtils.getSubject();

        //如果获取不到用户名就是登录失败,但登录失败的话,会直接抛出异常
        //登录
        subject.login(token);

        if (subject.hasRole("admin")) {
            return "redirect:/admin/showStudent";
        } else if (subject.hasRole("teacher")) {
            return "redirect:/teacher/showCourse";
        } else if (subject.hasRole("student")) {
            return "redirect:/student/showCourse";
        }

        return "/login";
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/92908.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git企业开发控制理论和实操-从入门到深入(五)|标签管理

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

前端需要理解的性能优化知识

优化的目的是展示更快、交互响应快、页面无卡顿情况。 1 性能指标 2 分析方法 使用 ChromeDevTool 作为性能分析工具来观察页面性能情况。其中Network观察网络资源加载耗时及顺序&#xff0c;Performace观察页面渲染表现及JS执行情况&#xff0c;Lighthouse对网站进行整体评分…

Mycat之前世今生

如果我有一个32核心的服务器&#xff0c;我就可以实现1个亿的数据分片&#xff0c;我有32核心的服务器么&#xff1f;没有&#xff0c;所以我至今无法实现1个亿的数据分片。——MyCAT ‘s Plan 话说“每一个成功的男人背后都有一个女人”&#xff0c;自然MyCAT也逃脱不了这个诅…

K8S集群中使用JDOS KMS服务对敏感数据安全加密 | 京东云技术团队

基本概念 KMS&#xff0c;Key Management Service&#xff0c;即密钥管理服务&#xff0c;在K8S集群中&#xff0c;以驱动和插件的形式启用对Secret&#xff0c;Configmap进行加密。以保护敏感数据&#xff0c; 驱动和插件需要使用者按照需求进行定制和实现自己的KMS插件&…

基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 5 Signal/States标签页介绍

这一篇我们说下signals和State这两个怎么搞做映射,那首先我们要知道什么是Signal和state,我们看下模型, 在原来的模型里我增加了标红的圆圈处delay模块,这个delay模块就是一个state模块,表示离散的一个状态,这个是个模型的基本概念,后续我有个专栏交接simulink建模,那…

ARTS打卡第二周之链表环的检测、gdb中disassemble的使用、底层学习建议、学习分享

Algorithm 题目&#xff1a;链表中环的检测 自己的分析见博客《检测链表中是否存在环》 Review disassemble command是我读的一篇英语文章&#xff0c;这篇文章主要是介绍gdb反汇编命令的使用和参数。自己为了能够演示这篇文章里边的内容&#xff0c;特意自己使用汇编语言编…

Apache Poi 实现Excel多级联动下拉框

由于最近做的功能&#xff0c;需要将接口返回的数据列表&#xff0c;输出到excel中&#xff0c;以供后续导入&#xff0c;且网上现有的封装&#xff0c;使用起来都较为麻烦&#xff0c;故参考已有做法封装了工具类。 使用apache poi实现excel联动下拉框思路 创建隐藏单元格&a…

深入探索快速排序:高效分而治之的算法

1. 引言&#xff1a;快速排序的背景与重要性 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;以其出色的性能和普适性而受到广泛关注。它利用了分而治之的思想&#xff0c;通过将数组分割成较小的子数组&#xff0c;并将这些子数组分别排序来实现…

DBeaver的安装和使用:windows版

DBeaver官网下载地址&#xff1a;https://dbeaver.io/download/ 下载完成后&#xff0c; 进入傻瓜式安装&#xff1a; 这里会进入重复界面&#xff0c;一样点击下一步即可 选择安装目录&#xff0c;尽量不要选C盘&#xff0c; 我的电脑只有c盘&#xff0c; 没办法 等待安装完成…

无涯教程-Python机器学习 - Semi-supervised Learning函数

Python机器学习 中的 Semi - 无涯教程网无涯教程网提供https://www.learnfk.com/python-machine-learning/machine-learning-with-python-semi-supervised-learning.html

c++ style casting

https://www.youtube.com/watch?vUfrR1nNfoeY&listPLE28375D4AC946CC3&index17

react +Antd Cascader级联选择使用接口数据渲染

1获取接口数据并将数据转换成树形数组 useEffect(() > {axios.get(/接口数据, {params: {“请求参数”},}).then((res) > {console.log(res);const getTreeData (treeData, pid) > {// 把数据转化为树型结构let tree [];let currentParentId pid || 0;for (let i …

PHP8的匿名函数-PHP8知识详解

php 8引入了匿名函数&#xff08;Anonymous Functions&#xff09;&#xff0c;它是一种创建短生命周期的函数&#xff0c;不需要命名&#xff0c;并且可以在其作用域内直接使用。以下是在PHP 8中使用匿名函数的知识要点&#xff1a; 1、创建匿名函数&#xff0c;语法格式如下&…

juc基础(三)

目录 一、读写锁 1、读写锁介绍 2、ReentrantReadWriteLock 3、例子 4、小结 二、阻塞队列 1、BlockingQueue 简介 2、BlockingQueue 核心方法 3、案例 4、常见的 BlockingQueue &#xff08;1&#xff09;ArrayBlockingQueue(常用) &#xff08;2&#xff09;Li…

NGINX相关配置

NGINX相关配置 NGINX配置信息 nginx 官方帮助文档&#xff1a;http://nginx.org/en/docs/Nginx的配置文件的组成部分&#xff1a; 主配置文件&#xff1a;/conf/nginx.conf(/nginx/conf/nginx.conf) 子配置文件: include conf.d/*.conf#事件驱动相关的配置 同步 event { wo…

Linux部署RocketMQ并使用SpringBoot创建生产、消费者

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;RocketMQ、消息队列☀️每日 一言&#xff1a;在你心灰意冷、心烦意乱时也不要停下你的脚步&#xff01; 一、前言 RocketMQ&#xff08;Apache RocketMQ&#xff09;是一种开源的分布式消息中间…

软件工程(十七) 行为型设计模式(三)

1、观察者模式 简要说明 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新 速记关键字 联动,广播消息 类图如下 基于上面的类图,我们来实现一个监听器。类图中的Subject对应我们的被观察对象接口(IObservable),…

基于加密接口的测试用例设计

这里写目录标题 一、环境准备二、原理三、实战练习 一、环境准备 1、对响应加密的接口。对它发起一个get请求后&#xff0c;得到一个加密过后的响应信息。(如果有可用的加密过的接口以及了解它的解密方法&#xff0c;可以跳过) 2、准备一个加密文件 加密字段 3、使用python…

如何将下载的安装包导入PyCharm

1. 下载安装包 这里以pyke为例。下载好之后解压缩&#xff0c;然后放入/Lib/site-packages/pyke-1.1.1 2. 打开PyCharm的终端进行安装 python setup.py install 3. 安装好之后导入即可使用 import pyke

Failed to load ApplicationContext解决办法,spring版本问题

有如下报错&#xff1a; "D:\Program Files\Java\jdk-13.0.1\bin\java.exe" -agentlib:jdwptransportdt_socket,address127.0.0.1:7325,suspendy,servern -ea -Didea.test.cyclic.buffer.size1048576 -Dfile.encodingUTF-8 -classpath "D:\Program Files\JetBr…