SpringSecurity Web 权限方案

目录

一、设置登录系统的账号、密码

二、数据库查询用户名密码

三、自定义登录页面

四、基于角色或权限进行访问控制

(一)hasAuthority 方法

(二)hasAnyAuthority 方法

(三)hasRole 方法

(四)hasAnyRole

五、自定义403页面 

六、注解使用

(一)@Secured

(二)@PreAuthorize

(三)@PostAuthorize

(四)@PreFilter

(五)@PostFilter

七、基于数据库的记住我

八、CSRF

 


一、设置登录系统的账号、密码

方式一,配置文件application.properties

spring.security.user.name=lucy
spring.security.user.password=123

方式二,编写配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String password = bCryptPasswordEncoder.encode("123");auth.inMemoryAuthentication().withUser("zhangsan").password(password).roles("admin");}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

方式三,通过类实现接口UserDetailService

@Service
public class userDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role");return new User("zhangsan", new BCryptPasswordEncoder().encode("123"), list);}
}

二、数据库查询用户名密码

引入依赖

        <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency>

建表sql

create table users(id bigint primary key auto_increment,username varchar(20) unique not null,password varchar(100)
);

数据源配置

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8username: rootpassword: 123456

实体类users

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Users {private Integer id;private String username;private String password;
}

mapper

@Mapper
public interface UserMapper extends BaseMapper<Users> {
}

修改userDetailService

@Service
public class userDetailsService implements UserDetailsService {@AutowiredUserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {// 使用mapper查询数据库QueryWrapper<Users> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username", s);Users users = userMapper.selectOne(queryWrapper);if (users == null) {throw new UsernameNotFoundException("用户名不存在!");}List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role");return new User(users.getUsername(), new BCryptPasswordEncoder().encode(users.getPassword()), list);}
}

修改SecurityConfigTest 

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

三、自定义登录页面

在配置类SpringSecurity中重写configure方法

    @Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin() //自定义自己编写的登录页面.loginPage("/login.html") //登录页面设置.loginProcessingUrl("/user/login") //登录访问路径.defaultSuccessUrl("/test/index").permitAll() //登录成功之后,跳转路径.and().authorizeRequests().antMatchers("/", "/test/hello","/user/login").permitAll() // 设置哪些路径可以直接访问,不需要认证.anyRequest().authenticated().and().csrf().disable(); // 关闭csrf防护}

再编写登录页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/user/login" method="post">用户名:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/><input type="submit" value="login"/></form>
</body>
</html>

controlller

@RestController
@RequestMapping("/test")
public class HelloController {@GetMapping("/hello")public String test() {return "hello, security";}@GetMapping("/index")public String index() {return "hello, index";}
}

启动项目后使用的登录页面就是我们编写的 了

 四、基于角色或权限进行访问控制

(一)hasAuthority 方法

如果当前的主体具有指定的权限,则返回 true,否则返回 false

设置访问/test/index需要admin角色

给用户添加admin角色 

 修改角色为别的,不是admin后访问被禁止

(二)hasAnyAuthority 方法

如果当前的主体有任何提供的角色(给定的作为一个逗号分隔的字符串列表)的话,返回 true.

(三)hasRole 方法

如果用户具备给定角色就允许访问 , 否则出现 403
如果当前主体具有指定的角色,则返回 true

底层源码:

 给用户添加角色需要加上前缀ROLE_

修改配置文件:
注意配置文件中不需要添加” ROLE_ “,因为上述的底层代码会自动添加与之进行匹配。

(四)hasAnyRole

表示用户具备任何一个条件都可以访问。
给用户添加角色:

修改配置文件:

五、自定义403页面 

在配置类中配置

编写unauth页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>没有访问权限</h1>
</body>
</html>

 跳转成功

六、注解使用

(一)@Secured

判断是否具有角色,另外需要注意的是这里匹配的字符串需要添加前缀“ ROLE_ “。
使用注解先要开启注解功能!
@EnableGlobalMethodSecurity(securedEnabled=true)
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled=true)public class DemosecurityApplication {public static void main(String[] args) {SpringApplication.run(DemosecurityApplication.class, args);}
}

 controller

    @GetMapping("/update")@Secured({"ROLE_admin"})public String update() {return "hello, update";}

(二)@PreAuthorize

先开启注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PreAuthorize:注解适合进入方法前的权限验证, @PreAuthorize 可以将登录用户的 roles/permissions 参数传到方法中。
    @GetMapping("/update")@PreAuthorize("hasAnyAuthority('admin')")public String update() {return "hello, update";}

(三)@PostAuthorize

先开启注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值的权限.

@RequestMapping("/testPostAuthorize")
@ResponseBody
@PostAuthorize("hasAnyAuthority('admin')")
public String preAuthorize(){System.out.println("test--PostAuthorize");return "PostAuthorize";
}

(四)@PreFilter

@PreFilter: 进入控制器之前对数据进行过滤
@RequestMapping("getTestPreFilter")
@PreAuthorize("hasRole('ROLE_管理员')")
@PreFilter(value = "filterObject.id%2==0")
@ResponseBody
public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> list){list.forEach(t-> {System.out.println(t.getId()+"\t"+t.getUsername());});return list;
}

(五)@PostFilter

@PostFilter :权限验证之后对数据进行过滤 留下用户名是 admin1 的数据
表达式中的 filterObject 引用的是方法返回值 List 中的某一个元素
@RequestMapping("getAll")
@PreAuthorize("hasRole('ROLE_管理员')")
@PostFilter("filterObject.username == 'admin1'")
@ResponseBody
public List<UserInfo> getAllUser(){ArrayList<UserInfo> list = new ArrayList<>();list.add(new UserInfo(1l,"admin1","6666"));list.add(new UserInfo(2l,"admin2","888"));return list;
}

七、基于数据库的记住我

使用spring security记住登录的用户原理

创建表

CREATE TABLE `persistent_logins` (`username` varchar(64) NOT NULL,`series` varchar(64) NOT NULL,`token` varchar(64) NOT NULL,`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

配置文件编写数据库的配置

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8username: rootpassword: 123456

配置类

默认 2 周时间。但是可以通过设置状态有效时间,即使项目重新启动下次也可以正常登录。

页面添加记住我复选框,此处: name 属性值必须为  remember-me. 不能改为其他值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/user/login" method="post">用户名:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/><input type="checkbox" name="remember-me"/>60s内免登录<br/><input type="submit" value="login"/></form>
</body>
</html>

八、CSRF

跨站请求伪造 (英语: Cross-site request forgery ),也被称为 one-click attack 或者 session riding ,通常缩写为 CSRF 或者 XSRF , 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。跟 跨网站脚本 XSS )相比, XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。
这利用了 web 中用户身份验证的一个漏洞: 简单的身份验证只能保证请求发自某个用户的浏览 器,却不能保证请求本身是用户自愿发出的
Spring Security 4.0 开始,默认情况下会启用 CSRF 保护,以防止 CSRF 攻击应用程序,Spring Security CSRF 会针对 PATCH POST PUT DELETE 方法进行防护。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合Dubbo和Zookeeper分布式服务框架使用的入门项目实例

文章目录 SpringBoot整合Dubbo和Zookeeper分布式服务框架使用的入门项目实例Dubbo定义其核心部分包含: 工作原理为什么要用dubbo各个节点角色说明&#xff1a;调用关系说明&#xff1a; dubbo为什么需要和zookeeper结合使用&#xff0c;zookeeper在dubbo体系中起到什么作用&…

Linux 部署

jdk&tomcat安装 1.上传jdk、tomcat安装包 2.解压两个工具包 #解压tomcat tar -zxvf apache-tomcat-8.5.20.tar.gz #解压jdk tar -zxvf jdk-8u151-linux-x64.tar.gz 3.配置并且测试jdk安装 #配置环境变量 vim /etc/profile #java environment export JAVA_HOME/root/soft/…

MySQL主从复制原理与实践:从配置到故障监控

文章目录 前言主从复制原理复制源主节点的工作从节点的工作复制流程的设计 主从复制环境搭建一、主从节点配置二、从节点开启复制步骤1、备份主节点的数据2、将数据同步到从节点3、从节点复制参数配置 三、验证复制环境 主从复制故障监控监控主从复制状态监控主从复制延迟 总结…

无/自监督去噪(1)——一个变迁:N2N→N2V→HQ-SSL

目录 1. 前沿2. N2N3. N2V——盲点网络&#xff08;BSNs&#xff0c;Blind Spot Networks&#xff09;开创者3.1. N2V实际是如何训练的&#xff1f; 4. HQ-SSL——认为N2V效率不够高4.1. HQ-SSL的理论架构4.1.1. 对卷积的改进4.1.2. 对下采样的改进4.1.3. 比N2V好在哪&#xff…

《软件方法》强化自测题-杂项(3)-少林足球巴别塔-不属于“软件方法建模师”考察范围

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 本套自测题不属于“软件方法建模师”考察范围。 自测链接&#xff1a;https://www.101test.com/cand/index?paperIdQR6CGK 1. [单选] 著名歌曲《橄榄树》&#xff08;不要问我从那…

【印象深刻的实战经历】学期末乐跑真实现状分析(以及解决方案)——开发一款期末顺利过关的简易功能乐跑软件soeasy面向初学安卓开发的人

目录 期末乐跑老师审查机制 总结如下 1. 老师会看你的乐跑次数够了没也就是这个页面 2. 老师会检查你的手机是否是自己的&#xff0c;也就是要看你乐跑的实名认证&#xff0c;也就是这个页面 以下是应对学期末乐跑的具体方法 第一步&#xff1a; 第二步&#xff1a; 第…

【 Qt 快速上手】-②- Qt 环境搭建

文章目录 1. Qt 开发工具概述1.1 Qt Creator 介绍1.2 Visual Studio 介绍1.3 Eclipse 介绍 2. Qt SDK 的下载与安装2.1 Qt SDK 的下载2.2 Qt SDK 的安装2.3 验证 Qt SDK 安装是否成功2.4 Qt 环境变量配置 1. Qt 开发工具概述 Qt 开发环境需要安装三个部分&#xff1a; C编译器…

CVE2020-1938漏洞复现

这个漏洞是tomcat的 然后我们先了解漏洞产生的原理 首先我们先来看tmocat纠结是干什么的 tomcat是个中间件 最主要的两个结构、 servlet的定义和部分源码&#xff0c; 漏洞就是从这来的 tomcat处理http请求 源码分析 tomcat 8.5.46 哎 这教学视频讲半天看不懂 不看原…

Windows使用docker安装redis

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十二&#xff09;——Windows系统下使用docker安装redis 文章目录 win系统环境搭建&#xff08;十二&#xff09;——Windows系统下使用docker安装redis1.创建文件夹2.docker-compose.yaml配置文件3.red…

力扣70. 爬楼梯(动态规划 Java,C++解法)

Problem: 70. 爬楼梯 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 由于本题目中第i层台阶只能由于第i- 1层台阶和第i-2层台阶走来&#xff0c;所以可以联想到动态规划&#xff0c;具体如下&#xff1a; 1.定义多阶段决策模型&#xff1a;对于每一上台阶看作一种状…

Hadoop3完全分布式搭建

一、第一台的操作搭建 修改主机名 使用hostnamectl set-hostname 修改当前主机名 关闭防火墙和SELlinux 1&#xff0c;使用 systemctl stop firewalld systemctl disable firewalld 关闭防火墙 2&#xff0c;使用 vim /etc/selinux/config 修改为 SELINUXdisabled 使用N…

Pycharm无法刷新远程解释器的框架: Can‘t get remote credentials for deployment server

在Pycharm上部署项目到远程服务器&#xff0c;有时候需要启动SSH会话&#xff0c;启动的时候发现没反应&#xff0c;且事件日志显示&#xff1a;无法刷新远程解释器的框架: Can’t get remote credentials for deployment server 观察pycharm界面最下边&#xff0c;发现“无默…