• Spring Security根据角色在登录后重定向用户


    在这篇 Spring Security 文章中,我想分享有关如何根据经过身份验证的用户在 Java Spring Boot Web 应用程序中的角色重定向经过身份验证的用户的步骤和代码示例。例如,当管理员用户登录时,他将看到“管理仪表板”页面。同样,具有角色编辑器的用户将在成功进行身份验证后看到编辑器仪表板页面。对于具有不同角色的不同用户,依此类推。假设您正在开发一个基于 Spring Boot Web、Spring Data JPA、Hibernate、Spring Security、Thymeleaf 和 MySQL 数据库的 Java Web 应用程序,并且已经实现了用户身份验证和基于角色的授权

     

    1. 在用户类中实现 hasRole 方法

    应用程序需要检查当前登录的用户是否具有特定角色。因此,在User实体类中对 hasRole() 方法进行编码,如下所示:如果为用户分配了指定的角色,则hasRole() 方法将返回 true,否则返回 false。并且还要更新您的自定义UserDetails类 – 添加hasRole() 方法,如下所示:Spring Security 将在身份验证成功后返回此UserDetails类的新实例。此类包装User 的一个实例,因此这里的hasRole() 方法只是将调用委托给User类。

    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
    package net.codejava;
     
    import java.util.*;
    import javax.persistence.*;
     
    @Entity
    @Table(name = "users")
    public class User {
         
        @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
        @JoinTable(
                name = "users_roles",
                joinColumns = @JoinColumn(name = "user_id"),
                inverseJoinColumns = @JoinColumn(name = "role_id")
                )
        private Set roles = new HashSet<>();
         
        public boolean hasRole(String roleName) {
            Iterator iterator = this.roles.iterator();
            while (iterator.hasNext()) {
                Role role = iterator.next();
                if (role.getName().equals(roleName)) {
                    return true;
                }
            }
             
            return false;
        }
         
        // other fields, getters and setters are not shown for brevity
    }

    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
    package net.codejava;
     
    public class CustomUserDetails implements UserDetails {
        private User user;
         
        public CustomUserDetails(User user) {
            this.user = user;
        }
     
        @Override
        public Collectionextends GrantedAuthority> getAuthorities() {
            Set roles = user.getRoles();
            List authorities = new ArrayList<>();
             
            for (Role role : roles) {
                authorities.add(new SimpleGrantedAuthority(role.getName()));
            }
            return authorities;
        }
     
         
        public boolean hasRole(String roleName) {
            return this.user.hasRole(roleName);
        }
         
        // other overriden methods are not shown
    }


    2. 代码认证成功处理程序

    接下来,编写一个扩展AuthenticationSuccessHandler 实现的类,例如SavedRequestAwareAuthenticationSuccessHander,如以下代码:你知道,当用户成功登录时,Spring Security 将调用onAuthenticationSuccess() 方法。因此,将重定向代码放在此方法中是非常合乎逻辑的,以便根据其角色重定向经过身份验证的用户。代码示例是不言自明的,所以我不必进一步解释。

    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
    36
    package net.codejava;
     
    import java.io.IOException;
     
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
     
    @Component
    public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
     
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws ServletException, IOException {
     
            CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
             
            String redirectURL = request.getContextPath();
             
            if (userDetails.hasRole("Salesperson")) {
                redirectURL = "sales_home";
            else if (userDetails.hasRole("Editor")) {
                redirectURL = "editor_home";
            else if (userDetails.hasRole("Shipper")) {
                redirectURL = "shipper_home";
            }
             
            response.sendRedirect(redirectURL);
             
        }
     
    }


    3. 配置 Spring 安全性以使用成功处理程序

    并更新 Spring 安全性配置类以使用身份验证成功处理程序类,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.shopme.admin.security;
     
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     
     
        @Override
        protected void configure(HttpSecurity http) throws Exception {
     
            http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/login")
                    .usernameParameter("email")
                    .successHandler(loginSuccessHandler)
                    .permitAll()
                .and()
                .logout().permitAll();
        }
         
        @Autowired private LoginSuccessHandler loginSuccessHandler;
    }
     

    要了解有关使用身份验证成功处理程序的更多信息,请参阅本文:Spring 安全性身份验证成功处理程序示例


    4. 更新视图图层

    此部分是可选的。如果基于角色的视图页面(编辑器主页、管理仪表板等)在控制器层中没有相应的处理程序方法,则可以在 Spring MVC 配置中配置视图名称解析,如下所示:这就是如何根据基于 Spring 引导和 Spring 安全性的 Java Web 应用程序中的角色重定向用户的全部内容。希望这篇文章对您有所帮助。要了解实际编码,我建议您观看以下视频:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package net.codejava;
     
    @Configuration
    public class MvcConfig implements WebMvcConfigurer {
     
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
            registry.addViewController("/sales_home").setViewName("sales_home");
            registry.addViewController("/editor_home").setViewName("editor_home");
            registry.addViewController("/shipper_home").setViewName("shipper_home");
        }
     
    }
  • 相关阅读:
    夯实算法-整数转罗马数字
    Vue和Element
    线控制动「放量」上攻
    Iframe通信
    LeetCode每日一题(1706. Where Will the Ball Fall)
    博客园商业化之路-开发任务众包平台:召集早期合作开发者
    粉丝推荐的 GitHub 项目 yyds
    技术分享 | JMeter性能测试实现与分析
    【Hello Go】Go语言并发编程
    Golang map
  • 原文地址:https://blog.csdn.net/allway2/article/details/127712327