页面重定向取决于使用 Spring 安全性和 Thymeleaf 的角色 - Spring

Posted

技术标签:

【中文标题】页面重定向取决于使用 Spring 安全性和 Thymeleaf 的角色 - Spring【英文标题】:Page redirecting depending on Role using Spring security and 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>

【问题讨论】:

【参考方案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”这样写,它永远不会带我进入我的登录页面。你知道怎么做吗?

以上是关于页面重定向取决于使用 Spring 安全性和 Thymeleaf 的角色 - Spring的主要内容,如果未能解决你的问题,请参考以下文章

具有 Spring 安全性的 JSF - 登录后重定向到指定页面

Spring 安全性和 Angular javascript 重定向到登录页面

会话超时后,Spring 安全性不会重定向到上次请求的页面登录

Spring Oauth和安全性在登录成功后重定向到/ login

使用Spring Social,Spring安全登录后重定向到原始URL?

Spring安全性重定向到经过身份验证的URL的登录页面