我已经和这个人争吵了一段时间。
我有一个Web应用程序,我试图将Spring Security放入其中。我已经成功地做到了这一点,每当用户试图访问他们未被授权的页面时,它就会将它们重定向到登录页面。问题是登录页面没有显示 - 只是登录页面的标题(并且它没有被风格化)。我很困惑,因为所有其他页面都显示正常。
This is the example I'm working from我几乎试图在信中跟随它,甚至已经下载了它,但我无法在我自己的项目中看到我做的不同。
我看到的唯一重大区别是我使用的是Gradle,这家伙正在使用Maven。
这是我的build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.7.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-spring-boot'
baseName = 'gs-handling-form-submission'
baseName = 'gs-serving-mobile-web-content'
baseName = 'gs-accessing-data-mongodb'
baseName = 'gs-rest-service-cors'
baseName = 'gs-securing-web'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
testCompile("org.springframework.boot:spring-boot-starter-test")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile 'junit:junit:4.12'
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile group: 'joda-time', name: 'joda-time', version: '2.8.1'
compile("org.springframework.boot:spring-boot-starter-web:1.3.0.RELEASE")
compile 'org.slf4j:slf4j-api:1.7.13'
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-parent:1.5.3.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile("org.springframework.boot:spring-boot-starter-mobile")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("com.h2database:h2")
compile("net.sourceforge.nekohtml:nekohtml:1.9.21")
compile("org.springframework.boot:spring-boot-starter-data-mongodb:1.2.0.RELEASE")
compile("org.springframework.boot.spring-boot-starter-remote-shell:1.2.0.RELEASE")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4")
compile("org.springframework.boot:spring-boot-devtools:true")
testCompile("org.springframework.security:spring-security-test")
compile("org.springframework.boot:spring-boot-starter-security")
}

这是我的控制器:
@Controller
public class WebController { //implements ErrorController{
private static final String PATH = "/error";
private BlogPostRepo blogPostRepo;
@Autowired
public WebController(BlogPostRepo blogPostRepo) {
this.blogPostRepo = blogPostRepo;
}
@RequestMapping("/index")
public String displayBlogPosts(Model model){
model.addAttribute("blogPosts", blogPostRepo.findAll());
return "index";
}
@RequestMapping("/login")
public String login(){
return "/login";
}
@GetMapping("/403")
public String error403() {
return "/error/403";
}
}

这是SpringSecurityConfig.java:
package com.stereoscopics.app.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
@Configuration
// http://docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html
// Switch off the Spring Boot security configuration
//@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccessDeniedHandler accessDeniedHandler;
// roles admin allow to access /admin/**
// roles user allow to access /user/**
// custom 403 access denied handler
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/index", "/submitAnArticle").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("password").roles("ADMIN");
}
}

这是我的AccessDeniedHandler.java:
package com.stereoscopics.app.error;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// handle 403 page
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
private static Logger logger = LoggerFactory.getLogger(MyAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException {
Authentication auth
= SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger.info("User '" + auth.getName()
+ "' attempted to access the protected URL: "
+ httpServletRequest.getRequestURI());
}
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");
}
}

这是我的登录信息:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
>
<head>
<title>Spring Security Example </title>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<div class="row" style="margin-top:20px">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
<form th:action="@{/login}" method="post">
<fieldset>
<h1>Please Sign In</h1>
<div th:if="${param.error}">
<div class="alert alert-danger">
Invalid username and password.
</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">
You have been logged out.
</div>
</div>
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg"
placeholder="UserName" required="true" autofocus="true"/>
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg"
placeholder="Password" required="true"/>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In"/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<div th:replace="fragments/footer :: footer"/>
</body>
</html>
&#13;
这是我的标题:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:fragment="header-css">
<!-- this is header-css -->
<link rel="stylesheet" type="text/css"
href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" th:href="@{/css/main.css}"
href="../../css/main.css" />
</div>
</head>
<body>
<div th:fragment="header">
<!-- this is header -->
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" th:href="@{/}">Spring Boot</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a th:href="@{/}">Home</a></li>
</ul>
</div>
</div>
</nav>
</div>
</body>
</html>
&#13;
以下是我尝试的内容:
检查文件路径 - 页眉和页脚位于\ resources \ templates \ fragments中,其他文件位于resources \ templates
谷歌(找不到任何东西)
仔细检查依赖关系
下载示例并交叉检查
我非常非常困惑。请帮忙。
答案 0 :(得分:-1)
如果没有可运行的示例(我可以克隆的git存储库会很好),很难调试,但我看到的一件事是您的安全配置需要身份验证才能访问样式表。
添加
.antMatchers("/webjars/**").permitAll()
.antMatchers("/css/**").permitAll()
到你的安全配置,样式表应该加载。
此外,您应该使用标题中样式表的绝对路径,因为 ../../ css / main.css 可能不适用于您的所有网址。
调试这些内容的一个好方法是在浏览器中使用Web控制台并查看网络请求,并查看是否所有资产都已正确加载。
答案 1 :(得分:-1)
您确定其登录页面显示不正确吗?我相信您可能会将未经过身份验证的请求重定向到错误的页面。处理MyAccessDeniedHandler类中被拒绝的请求时,执行以下命令:
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");
这又由WebController类处理,代码如下:
@GetMapping("/403")
public String error403() {
return "/error/403";
}
因此,当您处理403时,似乎您实际上并未呈现登录页面。
我不熟悉百里香叶,但我的猜测是你没有定义错误/ 403文件,即使在渲染页面时找不到html文件也会渲染一个标题。