Thymeleaf + Spring 安全集成基本知识

假设应用程序从使用JSP转向使用Themeleaf,本文将对Spring应用程序如何在登录页面、错误页面(login and error pages)使用Thymeleaf进行说明。本文讲述内容的代码,可以在GitHub上浏览和下载https://github.com/thymeleaf/thymeleafexamples-springsecurity

 Spring Security文档:http://docs.spring.io/spring-security/site/reference.html

1.登录页面(Login pages)

使用 Spring Security可以指定任意URL作为登录页面,例如:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
        .formLogin()
        .loginPage("/login.html")
        .failureUrl("/login-error.html")
      .and()
        .logout()
        .logoutSuccessUrl("/index.html");
}

下面在一个Spring 的Controller中对上述代码相关请求的路径匹配上方法

@Controller
public class MainController {

  ...

  // Login form
  @RequestMapping("/login.html")
  public String login() {
    return "login.html";
  }

  // Login form with error
  @RequestMapping("/login-error.html")
  public String loginError(Model model) {
    model.addAttribute("loginError", true);
    return "login.html";
  }

}

在上面的代码中,不管是/login.html还是/login-error.html最终使用的都是同一个模板( template)页面login.html。只不过在错误页面对应的方法中,给Model中的loginError赋值为Boolean值true,使其在login.html中可以获取,并显示Wrong user or password

login.html模板页面的代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Login page</title>
  </head>
  <body>
    <h1>Login page</h1>
    <p th:if="${loginError}" class="error">Wrong user or password</p>
    <form th:action="@{/login.html}" method="post">
      <label for="username">Username</label>:
      <input type="text" id="username" name="username" autofocus="autofocus" /> <br />
      <label for="password">Password</label>:
      <input type="password" id="password" name="password" /> <br />
      <input type="submit" value="Log in" />
    </form>
  </body>
</html>

 

2.错误页面(Error page)

Exception Handling in Spring MVC异常处理:https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

基于Thymeleaf配置error page,基本不涉及Spring Security,只需要简单的添加异常处理ExceptionHandler到自己项目的Spring配置中,如下所示

@ControllerAdvice
public class ErrorController {

    private static Logger logger = LoggerFactory.getLogger(ErrorController.class);

    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String exception(final Throwable throwable, final Model model) {
        logger.error("Exception during execution of SpringSecurity application", throwable);
        String errorMessage = (throwable != null ? throwable.getMessage() : "Unknown error");
        model.addAttribute("errorMessage", errorMessage);
        return "error";
    }

}

error.html模板页面如下

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Error page</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="css/main.css" th:href="@{/css/main.css}" />
    </head>
    <body th:with="httpStatus=${T(org.springframework.http.HttpStatus).valueOf(#response.status)}">
        <h1 th:text="|${httpStatus} - ${httpStatus.reasonPhrase}|">404</h1>
        <p th:utext="${errorMessage}">Error java.lang.NullPointerException</p>
        <a href="index.html" th:href="@{/index.html}">Back to Home Page</a>
    </body>
</html>

上面代码中,使用Spring’s HttpStatus是为了获取响应状态(response status)的详细信息。

 

@ResponseStatus

正常情况下,当一个web request导致服务器端返回一个HTTP 500的响应时,相应异常将会被抛出。然而,任何自己编写的异常处理均可以被@ResponseStatus标注,该标注支持所有的HTTP status code。当一个被@ResponseStatus标注的异常在项目的某Controller方法被抛出时,它会自动生成该自定义异常处理类中定义的合适的http响应和指定的响应码,然后将其返回。例如,下面是一个自定义的异常处理类,并使用@ResponseStatus进行标注。

 @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order")  // 404
 public class OrderNotFoundException extends RuntimeException {
     // ...
 }

下面的这段代码恰好使用了上面代码中自定义的异常处理

@RequestMapping(value="/orders/{id}", method=GET)
 public String showOrder(@PathVariable("id") long id, Model model) {
     Order order = orderRepository.findOrderById(id);

     if (order == null) throw new OrderNotFoundException(id);

     model.addAttribute(order);
     return "orderDetail";
 }

此时,若有一个不存在的order id出现在request请求的url中,则一个类似于404的经过我们自定义异常处理类处理之后的response将会被返回。

 

@ControllerAdvice+@ExceptionHandler实现Controller层全局异常处理

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    String handleException(){
        return "Exception Deal!";
    }
}

上述代码将会处理Controller层抛出的Exception及其子类对应的异常。若注解为@ExceptionHandler(Throwable.class)则可以处理Controller层抛出的Throwable对应的相关异常。

 

3.Spring安全方言(Spring Security Dialect

Spring Security 3 integration module    https://github.com/thymeleaf/thymeleaf-extras-springsecurity
Spring security taglib   https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/taglibs.html

在下面例子中使用Spring的安全方言去显示已登录用户的认证信息,针对不同的角色显示不同的内容。

 sec:authorize 当其属性表达式值为true的时候,将会显示相关设置的内容,代码如下

<div sec:authorize="isAuthenticated()">
  This content is only shown to authenticated users.
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
  This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
  This content is only shown to users.
</div>

sec:authentication属性用于输出已登录用户的用户名和角色

Logged user: <span sec:authentication="name">Bob</span>
Roles: <span sec:authentication="principal.authorities">[ROLE_USER, ROLE_ADMIN]</span>

 

                                       参考链接:https://www.thymeleaf.org/doc/articles/springsecurity.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值