• [Springboot]安全框架Spring Security使用


    一、介绍

    Spring Security是一个基于Spring框架的安全性框架。
    它提供了诸如认证、授权、攻击防御等功能,可以保护Web应用程序中的资源。

    二、作用

    认证(Authentication)

    验证用户的身份。

    授权(Authorization)

    限制用户对应用程序的访问。


    三、SpringBoot项目使用

    1、maven依赖

    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-securityartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、认证

    引入后项目就能使用了。
    未登录用户会自动跳转到Spring Security提供的登录页面。

    • 默认用户:user;
    • 默认密码:会在控制台打印Using generated security password: xxxxx 。

    2.1、认证配置——实现 UserDetailsService 接口

    登录不可能使用Spring Security默认配置,我们需要用自己的账户去登录。
    如果我们需要进行以下配置。

    @Service
    public class MyUserDetailsService implements UserDetailsService {
    
        public static record MyUser(String username,String password){};
        public MyUser queryUserFromDB(String username){
            //todo 自定义从数据库查询用户数据
            //这里我定死了一个用户
            return new MyUser(username,"123456");
        }
        // 自定义认证逻辑
        @Override
        public UserDetails loadUserByUsername(String username){
            // 1.查询用户
            MyUser user = queryUserFromDB(username);
            // 2.封装为UserDetails对象
            UserDetails userDetails = User
                    .withUsername(user.username)
                    .password(user.password)
                    .authorities("admin")
                    .build();
            // 3.返回封装好的UserDetails对象
            return userDetails;
        }
    
        /**
         * 配置密码解析器
         * 假如数据库密码没加密,使用NoOpPasswordEncoder
         * 假如数据库密码有加密,使用NBCryptPasswordEncoder
         * @return
         */
        @Bean
        public PasswordEncoder passwordEncoder(){
            return NoOpPasswordEncoder.getInstance();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2.2、登录页面配置——继承 WebSecurityConfigurerAdapter 类

    Spring Security提供了登录页面,但我们更多的是使用自己的登录页面。

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        //Spring Security配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // 自定义表单登录
            http.formLogin()
               .loginPage("/login.html") //自定义登录页面
               .usernameParameter("username")// 表单中的用户名项
               .passwordParameter("password")// 表单中的密码项
               .loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法
               .successForwardUrl("/index")//登录成功后跳转的路径
               .failureForwardUrl("/fail");//登录失败后跳转的路径
              // 配置需要认证的资源
             http.authorizeRequests()
             	.antMatchers("/login.html").permitAll() //登录页不需要认证
                .anyRequest().authenticated();//其余所有请求都需要认证
            //关闭csrf防护,默认开启了CSRF防护
            http.csrf().disable();
       }
        @Override
        public void configure(WebSecurity web) throws Exception {
            // 静态资源放行
          web.ignoring().antMatchers("/css/**");
          web.ignoring().antMatchers("/js/**");
          web.ignoring().antMatchers("/img/**");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.3、如果登录 成功/失败 需要额外处理。

    登录成功——实现AuthenticationSuccessHandler 接口
    public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
        @Override
        public void onAuthenticationSuccess(HttpServletRequest
    request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            // 拿到登录用户的信息
            UserDetails userDetails = (UserDetails)authentication.getPrincipal();
            //todo 自定义登录成功操作
            // 重定向到主页
            response.sendRedirect("/index");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在SecurityConfig 配置 AuthenticationSuccessHandler

    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        //Spring Security配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
        	//http.successForwardUrl("/index")
        	http.successHandler(new MyLoginSuccessHandler()) //登录成功处理器
        	//定义successHandler后就不用设置successForwardUrl
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    登录失败——实现AuthenticationFailureHandler 接口
    public class MyLoginFailureHandler implements AuthenticationFailureHandler {
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
    AuthenticationException exception) throws IOException, ServletException {
           	//todo 自定义失败操作
            response.sendRedirect("/fail");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在SecurityConfig 配置 AuthenticationFailureHandler

    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        //Spring Security配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
        	//http.failureForwardUrl("/fail");
        	http.failureHandler(new MyLoginFailureHandler());
        	//定义failureHandler后就不用设置failureForwardUrl
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.4、退出配置

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        //Spring Security配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // 退出登录配置
    		http.logout()
    		   .logoutUrl("/logout") // 退出登录路径
    		   .logoutSuccessUrl("/login.html") // 退出登录后跳转的路径
    		   .clearAuthentication(true) //清除认证状态,默认为true
    		   .invalidateHttpSession(true); // 销毁HttpSession对象,默认为true
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.5、Controller获取登录用户信息

    @RestController
    public class MyController {
        // 获取当前登录用户名
        @RequestMapping("/users/username")
        public String getUsername(){
            // 1.获取会话对象
            SecurityContext context = SecurityContextHolder.getContext();
            // 2.获取认证对象
            Authentication authentication = context.getAuthentication();
            // 3.获取登录用户信息
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            return userDetails.getUsername();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、鉴权

    3.1、@PreAuthorize

    注解会在方法执行前进行权限验证,支持Spring EL表达式,它是基于方法注解的权限解决方案。
    只有当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PreAuthorize才可以使用。

    @Configuration
    @EnableGlobalMethodSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
     	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用

    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/{userIds}")
    public Result get(@PathVariable long userId) {
       	//业务实现
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    原文 : https://developer.aliyun.com/article/1135702

  • 相关阅读:
    (二十)mmdetection源码解读:config配置文件models Faster R-CNN
    【JavaEE】JUC(Java.util.concurrent)常见类
    人工智能时代的离散数学教学研究
    Linux高性能服务器编程 学习笔记 第五章 Linux网络编程基础API
    基于Python实现的模拟退火算法
    supervisor 使用文档
    javascript基础七:说说你对Javascript中作用域的理解?
    CRM系统主要包括哪些功能?
    互联网摸鱼日报(2022-11-08)
    mysql语句心得
  • 原文地址:https://blog.csdn.net/malu_record/article/details/133849525