【问题标题】:Page redirecting depending on Role using Spring security and Thymeleaf - Spring页面重定向取决于使用 Spring 安全性和 Thymeleaf 的角色 - Spring
【发布时间】:2018-01-24 08:20:06
【问题描述】:

我正在使用 Spring security 和 Thymeleaf 开发我的项目。我有基本的 Spring Security 集成。

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private DataSource dataSource;

    @Autowired
      public void configureGlobal (AuthenticationManagerBuilder auth) throws Exception
      {
        auth
          .jdbcAuthentication()
            .dataSource(dataSource);
      }

    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
              .antMatchers("/login").permitAll()
              .antMatchers("/classesTable").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")

                .and()
            .httpBasic();
      } 
}

SecurityWebApplicationInitializer.java

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer
{
    public SecurityWebApplicationInitializer(){
        super(SecurityConfig.class);
    }

}

在我的项目中,我有三个角色:学生、教授和管理员。 我想要实现的是当我的学生登录时,他被重定向到页面 indexUser.html。当我的教授登录时,他被重定向到 indexProfesor.html,当管理员登录时,他登陆 indexAdmin.html 页面。

我想到了这样的事情

if(role.contains("ROLE_ADMIN")){
      //redirect from here to indexAdmin.html

    }else if(role.contains("ROLE_USER")) {
        //redirect to indexUser.html
    }else
        //redirect to indexProfesor.html
}

但我不知道整个控制器应该是什么样子。

让我的 homeContorller 看起来像这样:

@Controller
public class HomeController {

   @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginPage(Model model) {
        return "login";
    }
}

我也将此代码添加到我的 index.html 中

<span sec:authorize="isAuthenticated()">
<span sec:authentication="name"></span>
| Roles: <span sec:authentication="principal.authorities"></span> |

所以我熟悉登录用户的角色。 这也是我的 login.html 的代码

<form  th:action="@{/login}" method="post" class="l-form">
  <input type="text" name="username"/>
  <input type="password" name="password"/>
  <input type="hidden" th:name="${_csrf.parameterName}" 
   th:value="${_csrf.token}" />

   <button type="submit" class="btn">Sign in!</button>
</form>

【问题讨论】:

    标签: spring spring-boot spring-security thymeleaf


    【解决方案1】:

    找到适合我的解决方案。

    我将http.formLogin().defaultSuccessUrl("/success", true) 添加到我的SpringConfig 文件中。

    原来是这样的

    protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                  .antMatchers("/login").permitAll()
                  .antMatchers("/classesTable").hasRole("ADMIN")
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/success", true)
                    .and()
                .httpBasic();
          }
    

    然后我在 HomeController 中创建了一个名为 loginPageRedirect

    的新方法
    @Controller
    public class HomeController {
    
        @RequestMapping(value = "/login", method = RequestMethod.GET)
        public String loginPage(Model model) {
            return "login";
        }
        
        @RequestMapping("/success")
        public void loginPageRedirect(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException, ServletException {
            
            String role =  authResult.getAuthorities().toString();
            
            if(role.contains("ROLE_ADMIN")){
             response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + "/indexAdmin"));                            
             }
             else if(role.contains("ROLE_USER")) {
                 response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + "/indexUser"));
             }
        }
    
    }
    

    希望对遇到同样问题的人有所帮助。

    【讨论】:

    • 如果我们的回答对您有帮助,那么您可以投票给答案。此外,您可以接受哪个对您更有帮助。这是承认他人帮助的方式。谢谢
    • @sunkuet02 感谢这位朋友!
    【解决方案2】:

    第一道

    • 您可以将控制器方法更改为:

      @RequestMapping(value = "/login", method = RequestMethod.GET)
      public String loginPage(Model model, HttpServletRequest request) {
          if(request.isUserInRole("ROLE_ADMIN") {
               // redirect to indexAdmin.html page
          } else if(request.isUserInRole("ROLE_USER") {
               // redirect indexUser.html page
          } else {
               // redirect to indexProfesor.html page
          }
      }
      

      Spring MVC 会自动在request 参数中注入少量HttpServletRequest 属性,使用这个你可以受益。

    另一种方式

    • 您可以将控制器方法更改为:

      @RequestMapping(value = "/login", method = RequestMethod.GET)
      public String loginPage(Model model, Authentication authentication) {
          if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
              // redirect to indexAdmin.html page
          } else if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_USER"))) {
              // redirect indexUser.html page
          } else {
              // redirect to indexProfesor.html page
          }
      }
      

      这里,Spring MVC 会自动将Authentication 属性注入authentication 对象。

    【讨论】:

    • 我已经熟悉我的用户所拥有的角色。检查我的代码更新。我正在尝试根据他的角色将他重定向到不同的页面。 @sunkuet02
    • 我刚刚对我得到的其他答案写了评论... 我认为我需要使用映射制作单独的控制器,例如“/successLogin”,然后将您在上面编写的逻辑放入其中.如果我用映射“/login”这样写,它永远不会带我进入我的登录页面。你知道怎么做吗?
    • @dome,有login.jsp页面吗?
    • 你可以在/login控制器方法中写return "redirect:login.html";作为返回语句。如果不起作用,请尝试不使用.html
    【解决方案3】:

    您可以在控制器方法中公开 Spring MVC 将为您注入的 HttpServletRequest 参数,然后使用 HttpServletRequest#isUserInRole(String)

    还假设您已将视图映射如下:

    • "indexAdmin" -> "/your/static/resource/indexAdmin.html"
    • "indexUser" -> "/your/static/resource/indexUser.html"
    • "indexProfesor" -> "/your/static/resource/indexProfesor.html"

    方法如下:

       @Controller
        public class HomeController {
    
           @RequestMapping(value = "/login", method = RequestMethod.GET)
            public String loginPage(HttpServletRequest httpServletRequest, Model model) {
                if(httpServletRequest.isUserInRole("ADMIN")) {
                    return "indexAdmin";
                } else if(httpServletRequest.isUserInRole("USER")) {
                    return "indexUser";
                } else {
                    return "indexProfesor";
                }
            }
        }
    

    如上面的 Spring 文档链接中所述:

    [..]通常用户不应将“ROLE_”前缀传入此 方法[..]

    【讨论】:

    • 感谢您的评论。我想我需要使用映射制作单独的控制器,例如“/successLogin”,然后将您在上面编写的逻辑放入其中。如果我用映射“/login”这样写,它永远不会带我进入我的登录页面。你知道怎么做吗?
    猜你喜欢
    • 2014-03-26
    • 1970-01-01
    • 2014-02-06
    • 2020-09-10
    • 2014-04-14
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    相关资源
    最近更新 更多