详解springboot springsecuroty中的注销和权限控制问题

详解 Spring Boot Spring Security 中的注销和权限控制问题

前言

Spring Boot Spring Security 是一个非常常用的技术组合,它们可以提供很好的安全性,和身份认证、授权、限制等重要功能,但是在实际开发中可能会遇到注销和权限控制相关的问题,需要我们了解并深入研究。

正文

注销功能

注销功能是常见的需求,用户在退出应用之前需要先注销,以免敏感信息泄露。在 Spring Security 中,我们可以通过配置实现注销功能。

首先,我们需要在 Spring Security 的配置类中添加注销的代码:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .deleteCookies("JSESSIONID");
    }

}

上述代码中,我们通过 logout() 方法实现注销功能。其中,参数 .logoutUrl("/logout") 用于指定注销 URL 地址,.logoutSuccessUrl("/") 用于指定注销成功后跳转到的URL地址,.invalidateHttpSession(true) 用于清除会话中的资源,在我们给用户分配的权限需要在会话中持久化的时候,需要把会话中的所有信息清除,.clearAuthentication(true) 用于清除身份验证信息,.deleteCookies("JSESSIONID") 需要删除所有的会话 cookies。

我们还需要在 Spring Boot 应用中添加与实现注销功能相关的接口方法:

@Controller
public class LogoutController {

    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){    
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout";
    }

}

这里我们通过 SecurityContextHolder.getContext().getAuthentication() 获取认证信息,再通过 SecurityContextLogoutHandler().logout(request, response, auth) 处理注销,在完成注销后跳转到登录页面并携带提示信息。

权限控制

权限控制是指针用户访问特定资源时,需要满足一定的条件才能访问。在 Spring Security 中,我们可以通过配置 HttpSecurity 实现权限控制。

在权限控制时,我们需要实现一个自定义的 UserDetailsService。下面是实现方法示例:

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> userOptional = userRepository.findByUsername(username);
        User user = userOptional.orElseThrow(() -> new UsernameNotFoundException(String.format("User %s not found!", username)));
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthority());
    }

    private List<SimpleGrantedAuthority> getAuthority() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
    }

}

然后我们在 Spring Security 中配置权限控制:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasRole("USER")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .deleteCookies("JSESSIONID");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

在上述配置中,我们通过 .antMatchers() 指定需要限制的路径和需要满足的条件,在这里使用了 hasRole("ADMIN")hasRole("USER") 指定了访问这些路径的角色,.anyRequest().authenticated() 表示所有的请求都需要认证以后才能请求,这很重要,否则授权可能不起作用。

示例

注销功能示例:

在 HTML 页面中添加注销按钮:

<a th:href="@{/logout}">Logout</a>

然后处理注销请求的 Controller:

@Controller
public class LogoutController {

    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){    
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout";
    }

}

权限控制示例:

在 HTML 页面中添加不同的请求路径:

<a th:href="@{/admin/hello}">Hello for Admin</a>
<a th:href="@{/user/hello}">Hello for User</a>

然后在 Controller 中处理这些请求:

@Controller
public class HomeController {

    @RequestMapping(value={"/", "/home"})
    public String home(){
        return "home";
    }

    @RequestMapping(value="/admin/hello", method = RequestMethod.GET)
    public String helloAdmin(){
        return "hello_admin";
    }

    @RequestMapping(value="/user/hello", method = RequestMethod.GET)
    public String helloUser(){
        return "hello_user";
    }

}

最后在 mySQL 数据库中添加用户和角色信息:

username password role
admin 123456 ADMIN
user 123456 USER

这样,我们就可以实现注销和权限控制的功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解springboot springsecuroty中的注销和权限控制问题 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Java创建对象的几种方法

    下面我将详细讲解 Java 创建对象的几种方法。 一、通过 new 关键字创建对象 使用 new 关键字可以在堆内存中创建对象。它也是创建对象最常见和最基本的方法。 语法如下: 类名 对象名 = new 类名(); 示例1: // 创建一个 Person 类的对象 Person person = new Person(); 示例2: // 创建一个 Stri…

    Java 2023年5月26日
    00
  • Java执行shell命令的实现

    Java可以通过运行shell命令来与操作系统进行交互,可以使用以下三种方式来执行shell命令: Runtime类 ProcessBuilder类 Process类 Runtime类 Java中有一个常量对象Runtime代表着当前Java应用程序的运行环境,可以使用Runtime类中的exec()方法在程序中执行shell命令。 import java.…

    Java 2023年5月26日
    00
  • php 来访国内外IP判断代码并实现页面跳转

    让我详细讲解一下“php 来访国内外IP判断代码并实现页面跳转”的完整攻略。 1. 获取客户端IP 在PHP中获取客户端IP地址的方式有很多,其中一种常用的方式就是使用$_SERVER[‘REMOTE_ADDR’]。这个变量会返回客户端访问当前页面的IP地址。 以下是一个示例代码: $ip = $_SERVER[‘REMOTE_ADDR’]; echo &q…

    Java 2023年6月16日
    00
  • 如何用注解的方式实现Mybatis插入数据时返回自增的主键Id

    下面详细讲解如何用注解的方式实现Mybatis插入数据时返回自增的主键Id。 首先,在处理插入操作时,通常需要获取数据库自动生成的主键Id,以便后续处理。使用Mybatis时,可以使用useGeneratedKeys和keyProperty两个属性来实现此功能。 其中,useGeneratedKeys表示是否使用数据库自动生成的主键,默认值是false;而k…

    Java 2023年5月20日
    00
  • SpringBoot集成Kafka 配置工具类的详细代码

    下面是详细讲解SpringBoot集成Kafka配置工具类的完整攻略。 1、前置要求 在进行SpringBoot集成Kafka之前,需要准备以下环境: Java JDK 8及以上版本 Maven构建工具 Kafka集群及对应的Zookeeper集群 2、添加依赖 在进行SpringBoot集成Kafka之前,需要在pom.xml中添加以下依赖: <de…

    Java 2023年5月20日
    00
  • 目前最全的python的就业方向

    当谈到Python就业方向时,受众人群极为广泛。无论您是新手,依靠Python技能入行,还是跨专业发展、想要转行为Python工程师,或是已经加入工程师界,希望扩大技能栈,这些适用于每个等级的就业方向,对于Python开发人员来说都是有用的。 以下是目前最全的Python的就业方向的攻略: 1. Web开发 Web开发是目前Python领域中的主要就业方向之…

    Java 2023年5月26日
    00
  • Java函数式编程(七):MapReduce

    当我们需要对一个集合进行聚合并计算时,MapReduce是非常有用的编程方法。在Java函数式编程中,我们可以利用Stream API实现MapReduce。 MapReduce概述 MapReduce是一种编程模型,用于处理大规模的数据集。它将工作分成了两个阶段:Map和Reduce。Map阶段将数据分割成更小的数据块,然后对每个数据块进行处理。Reduc…

    Java 2023年5月26日
    00
  • 使用java.nio.file 库优雅的操作文件详解

    使用Java.nio.file库可以实现优雅而高效的文件操作。Java.nio.file库提供了几个主要的类和方法,包括Path、Files和FileSystem等。下面详细讲解如何使用这些类和方法来完成文件操作。 Path类 Path类代表一个文件或目录的路径。可以通过Paths类的静态方法获取一个Path对象,例如: Path path = Paths.…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部