如何在 Spring Boot 应用程序中包含 Spring Security
Posted
技术标签:
【中文标题】如何在 Spring Boot 应用程序中包含 Spring Security【英文标题】:How to include Spring Security in a spring boot application 【发布时间】:2019-05-08 20:59:56 【问题描述】:我正在开发一个 Spring Boot 应用程序。在开发应用程序之后,我们现在正尝试在我们的应用程序中包含 Spring Security。
我已包含以下代码:
html代码:
<li th:if="$#authorization.expression('!isAuthenticated()')">
<a th:href="@/login" th:text="#navbar.login.text" />
</li>
Java 代码:
package com.devopsbuddy.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
private static final String[] PUBLIC_MATCHERS =
"/webjars/**",
"/css/**",
"/js/**",
"/images/**",
"/",
"/about/**",
"/contact/**",
"/error/**/*"
;
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers(PUBLIC_MATCHERS).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/payload")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth
.inMemoryAuthentication()
.withUser("user").password("password")
.roles("USER");
当我尝试点击网址时:
http://localhost:8080/
我在屏幕上收到以下错误:
**36673 [http-nio-8080-exec-2] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][http-nio-8080-exec-2] Exception processing template "user/login": Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:125)
...
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method expression(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:153)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:82)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:67)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:111)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:328)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263)
... 102 common frames omitted
36673 [http-nio-8080-exec-2] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)] with root cause
org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method expression(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:153)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:82)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:67)**
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
我是 Thymeleaf 和 Spring 安全的新手。所以不知道为什么 Spring 安全性失败了。
如果我用 authorization.expression() 注释该行,它会起作用。
我已在分支安全中的https://github.com/azaveri7/devopsbuddy 共享代码。
请指教。
【问题讨论】:
Spring boot 如果在类路径中发现 spring 安全依赖项,它将自动使用登录保护您的 url,您所要做的就是自定义它,例如不应该限制哪些 url 或您的自定义登录页面。 check 在您的控制器中进行身份验证,而不是在 thymeleaf 模板中使用它。 【参考方案1】:请将此视为建议,而不是答案。以前我也经历过这个,但很难弄清楚。然后我决定通过spring的自动配置。我只使用了这个库 -
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
然后spring提供了登录URL、登录页面、注销URL等。我只写了userdetailsService。就我而言,我还编写了一个自定义过滤器。
【讨论】:
【参考方案2】:我有以下检查用户是否未登录
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
....
<span sec:authorize="not isAuthenticated()">
You are not logged in - click <a th:href="@/login">login</a>
</span>
...
【讨论】:
【参考方案3】:你的 pom 中的 spring 安全性是 5.0.9,它扩展了 spring-boot-starter-parent 2.0.6
BUT thymeleaf-extras-springsecurity4 仍然是 spring security 4,所以你需要将 thymeleaf-extras 升级到
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
【讨论】:
以上是关于如何在 Spring Boot 应用程序中包含 Spring Security的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot Actuator Prometheus 指标中包含时间戳
在 Spring Boot Camel 应用程序公开的 Micrometer / Prometheus 信息中包含其他 JMX 指标