前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 下

Spring Security 下

作者头像
张小驰出没
发布2021-05-08 14:34:11
5390
发布2021-05-08 14:34:11
举报
文章被收录于专栏:用户8506532的专栏

Spring Security 下

Security 注解使用

1.@Secured

判断是否具有角色,另外需要注意的是这里匹配的字符串需要添加前缀 ROLE

1.在 启动类 或者 配置类 上加入注解 开启该注解

代码语言:javascript
复制
@EnableGlobalMethodSecurity(securedEnabled = true)

2.Controller层加入方法注解

代码语言:javascript
复制
@GetMapping("/update")
@Secured({"ROLE_sale","ROLE_man"})   //有该权限才可以
public String update(){
    return "update";
}

3.在UserDetailsService实现类中添加权限

代码语言:javascript
复制
List<GrantedAuthority> auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_user");

4.运行测试

你登陆之后,如果登录用户没有对应权限,就算是可以登陆上去,也无法进入该路径

2.@PreAuthorize

该注解适合进入方法前的权限验证 ,可以将登录用户的 roles/permissions 参数传到方法中。.

1.在 启动类 或者 配置类 上加入注解 开启该注解

代码语言:javascript
复制
@EnableGlobalMethodSecurity(prePostEnabled = true)

2.Controller层加入方法注解

代码语言:javascript
复制
@GetMapping("/update")
@PreAuthorize("hasAnyAuthority('admins')")
    /* @PreAuthorize("hasAnyAuthority('admins')") 
    *  @PreAuthorize("hasRole('admins')")
    */ @PreAuthorize("hasAnyRole('admins')")
public String update(){
    return "update";
}

3.在UserDetailsService实现类中添加权限

代码语言:javascript
复制
List<GrantedAuthority> auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_user");

4.运行测试

该方法,与在配置类中给网页加上进入权限相同,连四个方法都完全一样

3.@PostAuthorize

该注解使用不多,在方法执行后再进行权限验证,适合验证带有返回值的权限

1.在 启动类 或者 配置类 上加入注解 开启该注解

代码语言:javascript
复制
@EnableGlobalMethodSecurity(prePostEnabled = true)

2.Controller层加入方法注解

代码语言:javascript
复制
@GetMapping("/update")
@PostAuthorize("hasAnyAuthority('admin')")  //也是参数为 四种方法
public String update(){
    System.out.println("update。。。");
    return "update";
}

3.在UserDetailsService实现类中添加权限

代码语言:javascript
复制
List<GrantedAuthority> auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_user");

4.运行测试

该注解下,虽然权限不足仍然无法进入页面或者返回信息,但是可以先运行方法体中的内容,再校验

所以对于上面的实例,进入路径后,虽然还是显示 没权限403,但是 update 会输出

4.@PostFilter

权限验证之后对返回的数据进行过滤

1.在 启动类 或者 配置类 上加入注解 开启该注解

代码语言:javascript
复制
@EnableGlobalMethodSecurity(prePostEnabled = true)

2.Controller层加入方法注解

代码语言:javascript
复制
@GetMapping("getAll")
@PostAuthorize("hasAnyAuthority('admins') ")
@PostFilter("filterObject.username == 'admin1'")
public List<Users> getAllUser() {
    ArrayList<Users> list = new ArrayList<>();
    list.add(new Users(1, "admin1", "666"));
    list.add(new Users(2, " admin2", "888"));
    return list;
}

3.在UserDetailsService实现类中添加权限

代码语言:javascript
复制
List<GrantedAuthority> auths =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_user");

4.运行测试

1
1

5.@PreFilter

进入控制器之前对传递回来的数据进行过滤

@PostFilter 类似, 不做演示

用户注销

1.创建登录成功页面

代码语言:javascript
复制
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    登录成功!
    <a href="/logout">退出a>
body>
html>

2.配置类中配置注销功能

代码语言:javascript
复制
@Override
protected void configure(HttpSecurity http) throws Exception {
    //注销,第一个路径为 退出是设置的路径 ; 第二个路径为 成功退出后的路径
    http.logout().logoutUrl("/logout").logoutSuccessUrl("/login.html").permitAll();
    http.exceptionHandling().accessDeniedPage("/uuauth.html");
    http.formLogin()   
        .loginPage("/login.html") 
        .loginProcessingUrl("/user/login") 
        .defaultSuccessUrl("/success.html").permitAll()  //这里更换为登录成功页面
        .and().authorizeRequests()
        .antMatchers("/","/hello","/user/login") 
        .permitAll()
        .antMatchers("/index").hasRole("user")
        .anyRequest().authenticated()
        .and().csrf().disable(); 
}

3.运行测试

上述两个操作已经足够了

登录页面之后,会出现在 成功登录页面 ,这时候 你进入其他的页面也是可以的(如果权限允许)

点击退出,返回设置好的页面,这时候 其他页面都无法进入

基于数据库实现记住我

2
2

步骤:

  1. 创建数据库
  2. 配置类 、配置数据源
  3. 配置类中 配置 自动登录
  4. 登陆页面添加 复选框

1.创建数据库

该数据库语句是 Security 框架中 内置的创建语句

代码语言:javascript
复制
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

2.配置数据源

代码语言:javascript
复制
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository(){
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    jdbcTokenRepository.setDataSource(dataSource);
    // jdbcTokenRepository.setCreateTableOnStartup(true);  启动时 创建表
    return jdbcTokenRepository;
}

3.配置自动登录

代码语言:javascript
复制
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.logout().logoutUrl("/logout").logoutSuccessUrl("/login.html").permitAll();
    http.exceptionHandling().accessDeniedPage("/uuauth.html");
    http.formLogin()   
        .loginPage("/login.html")  
        .loginProcessingUrl("/user/login") 
        .defaultSuccessUrl("/success.html").permitAll()  
        .and().authorizeRequests()
        .antMatchers("/","/hello","/user/login") 
        .permitAll()   
        .antMatchers("/index").hasRole("user")
        .anyRequest().authenticated()
        
        .and().rememberMe().tokenRepository(persistentTokenRepository())
        .tokenValiditySeconds(60)   //设置有效时长
        .userDetailsService(userDetailsService)

        .and().csrf().disable(); 
}

4.登陆页面添加 记住我

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post" action="/user/login">
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="text" name="password">
        <br>
        <input type="checkbox" name="remember-me"> 自动登录   <!-- name 必须为 "remember-me"  -->
        <br>
        <input type="submit" value="login">
    </form>
</body>
</html>

5.运行测试

等着之后,数据会存在 cookie 中 ; 也因为数据库为框架内部设置好的,所以也会存在数据库表中

3
3
4
4

CSRF 保护

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack“或者Session Riding,通常缩写为CSRF或XSRF,是一种对网站的恶意攻击。是一种依赖web浏览器的、被混淆过的代理人攻击。 常见特性:

  • 依靠用户标识危害网站
  • 利用网站对用户表识的信任
  • 欺骗用户的浏览器发送HTTP请求给目标站点
  • 可以通过IMG标签会触发一个GET请求,可以利用它来实现CSRF攻击。

该种方式只能对 POSTPUTDELETEPATCH 发送方式进行保护

1.引入依赖

代码语言:javascript
复制
<dependency>
    <groupId>org.thymeleaf.extrasgroupId>
    <artifactId>thymeleaf-extras-springsecurity4artifactId>
    <version>3.0.2.RELEASEversion>
dependency>

2.创建CSRF测试前端页面

先直接在static文件夹下创建一个login页面

代码语言:javascript
复制
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    <form method="post" action="/user/login">
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="text" name="password">
        <br>
        <input type="checkbox" name="remember-me"> 自动登录
        <br>
         <input type="submit" value="login">
    form>
body>
html>

首先在resources文件夹下创建 templates 文件夹, Spring Boot 默认Controller层跳转路径为该文件夹下页面

csrf.html

代码语言:javascript
复制
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    <form method="post" action="token">
        
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="text" name="password">

         <input type="submit" value="login">
    form>
body>
html>

csrf_success.html

代码语言:javascript
复制
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    <span th:text="${_csrf.token}">span> <br>
body>
html>

3.创建Controller层代码

代码语言:javascript
复制
@Controller
public class CSRFController {

    @GetMapping("/csrf")
    public String csrf(Model model) {
        return "csrf";
    }
    @PostMapping("/csrf_success")
    public String success() {
        return "csrf_success";
    }
}

4.修改配置类代码

代码语言:javascript
复制
http.formLogin()
    .loginProcessingUrl("/user/login") 
    .defaultSuccessUrl("/").permitAll() 
    .and().authorizeRequests()
    .antMatchers("/","/csrf","/user/login") 
    .permitAll();
//	.and().csrf().disable(); //关闭csrf

5.运行测试

这时候已经将CSRF开启了,这时候进入测试路径:

http://localhost:8081/csrf

输入账号密码,会成功进入 /csrf_success ; 并且页面中显示 _csrf.token

5
5
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/05/06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Security 下
    • Security 注解使用
      • 1.@Secured
      • 2.@PreAuthorize
      • 3.@PostAuthorize
      • 4.@PostFilter
      • 5.@PreFilter
    • 用户注销
      • 基于数据库实现记住我
        • CSRF 保护
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档