当我尝试实现Spring安全性时,我收到以下错误 -
控制器:
@Controller
public class EmployeeController {
@RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
public ModelAndView defaultPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security + Hibernate Example");
model.addObject("message", "This is default page!");
model.setViewName("hello");
return model;
}
@RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security + Hibernate Example");
model.addObject("message", "This page is for ROLE_ADMIN only!");
model.setViewName("admin");
return model;
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout,
HttpServletRequest request) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error",
getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("login");
return model;
}
// customize the error message
private String getErrorMessage(HttpServletRequest request, String key) {
Exception exception = (Exception) request.getSession()
.getAttribute(key);
String error = "";
if (exception instanceof BadCredentialsException) {
error = "Invalid username and password!";
} else if (exception instanceof LockedException) {
error = exception.getMessage();
} else {
error = "Invalid username and password!";
}
return error;
}
// for 403 access denied page
@RequestMapping(value = "/403", method = RequestMethod.GET)
public ModelAndView accesssDenied() {
ModelAndView model = new ModelAndView();
// check if user is login
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
System.out.println(userDetail);
model.addObject("username", userDetail.getUsername());
}
model.setViewName("403");
return model;
}
}
的web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- /WEB-INF/spring-security.xml -->
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
弹簧security.xml文件
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf />
</http>
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService" >
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
</beans:beans>
的login.jsp
<body onload='document.loginForm.username.focus();'>
<h1>Spring Security Login Form (Database + Hibernate Authentication)</h1>
<div id="login-box">
<h3>Login with Username and Password</h3>
<c:if test="${not empty error}">
<div class="error">${error}</div>
</c:if>
<c:if test="${not empty msg}">
<div class="msg">${msg}</div>
</c:if>
<form name='loginForm'
action="<c:url value='/j_spring_security_check' />" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username'></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" /></td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
</div>
</body>
错误: -
http://localhost:8080/EmployeeManagement/j_spring_security_check
09:01:22.135 [http-8080-4] DEBUG o.s.s.web.DefaultRedirectStrategy - 重定向到&#39; http://localhost:8080/EmployeeManagement/login;jsessionid=E27C22793BAA2C7FC38039260EC08152&#39; 09:01:22.135 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。 09:01:22.136 [http-8080-4] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成 09:01:22.145 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录位置1的11;触发过滤器:&#39; SecurityContextPersistenceFilter&#39; 09:01:22.145 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession为SPRING_SECURITY_CONTEXT返回了null对象 09:01:22.145 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - 没有来自HttpSession的SecurityContext:org.apache.catalina.session.StandardSessionFacade@48842f5e。将创建一个新的。 09:01:22.145 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第2位的第11位登录其他过滤链;烧制过滤器:&#39; CsrfFilter&#39; 09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录位置3的11;触发过滤器:&#39; LogoutFilter&#39; 09:01:22.146 [http-8080-4] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - 请求&#39; GET / login&#39;没有匹配&POST; j /spring_security_logout 09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录第4位的11位;触发过滤器:&#39; UsernamePasswordAuthenticationFilter&#39; 09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录位置5的11;触发过滤器:&#39; BasicAuthenticationFilter&#39; 09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录第6位的第11位;触发过滤器:&#39; RequestCacheAwareFilter&#39; 09:01:22.146 [http-8080-4] DEBUG o.s.s.w.s.DefaultSavedRequest - pathInfo:都为null(属性等于) 09:01:22.147 [http-8080-4] DEBUG o.s.s.w.s.DefaultSavedRequest - queryString:都为null(属性等于) 09:01:22.147 [http-8080-4] DEBUG o.s.s.w.s.DefaultSavedRequest - requestURI:arg1 = / EmployeeManagement / admin; arg2 = / EmployeeManagement / login; jsessionid = E27C22793BAA2C7FC38039260EC08152(属性不等于) 09:01:22.147 [http-8080-4] DEBUG o.s.s.w.s.HttpSessionRequestCache - 保存的请求不匹配 09:01:22.147 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录第7位的第11位;触发过滤器:&#39; SecurityContextHolderAwareRequestFilter&#39; 09:01:22.147 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第8位的11位登录另一个过滤链;触发过滤器:&#39; AnonymousAuthenticationFilter&#39; 09:01:22.147 [http-8080-4] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - 带有匿名标记的填充SecurityContextHolder:&#39; org.springframework.security.authentication.AnonymousAuthenticationToken@6fa90ed4:Principal:anonymousUser;证书:[保护];认证:真实;详细信息:org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c:RemoteIpAddress:0:0:0:0:0:0:0:1; SessionId:E27C22793BAA2C7FC38039260EC08152;授权机构:ROLE_ANONYMOUS&#39; 09:01:22.147 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录第9位的第11位;触发过滤器:&#39; SessionManagementFilter&#39; 09:01:22.148 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第10位的11位登录其他过滤链;触发过滤器:&#39; ExceptionTranslationFilter&#39; 09:01:22.148 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第11位的11位登录附加过滤链;触发过滤器:&#39; FilterSecurityInterceptor&#39; 09:01:22.148 [http-8080-4] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - 检查请求的匹配:&#39; / login&#39 ;;反对&#39; / admin **&#39; 09:01:22.148 [http-8080-4] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - 公共对象 - 未尝试身份验证 09:01:22.148 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - / login已达到额外过滤器链的末尾;继续与原始链 09:01:22.148 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet,名称为&#39; mvc-dispatcher&#39;处理[/ EmployeeManagement / login]的GET请求 09:01:22.149 [http-8080-4] DEBUG o.s.w.s.m.a.DefaultAnnotationHandlerMapping - 使用处理程序[com.employeemgmt.controller.EmployeeController@18ba5047]和1个拦截器将[/ login]映射到HandlerExecutionChain 09:01:22.150 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - [/ EmployeeManagement / login]的Last-Modified值为:-1 09:01:22.189 [http-8080-4] DEBUG oswbasHandlerMethodInvoker - 调用请求处理程序方法:public org.springframework.web.servlet.ModelAndView com.employeemgmt.controller.EmployeeController.login(java.lang.String,java.lang .String,javax.servlet.http.HttpServletRequest) 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 在bean上调用afterPropertiesSet(),名称为&#39; login&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean的缓存实例&#39; org.springframework.transaction.config.internalTransactionAdvisor&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean的缓存实例&#39; org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean的缓存实例&#39; org.springframework.transaction.config.internalTransactionAdvisor&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean的缓存实例&#39; org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - 渲染视图[org.springframework.web.servlet.view.JstlView:name&#39; login&#39 ;; DispatcherServlet中的URL [/WEB-INF/pages/login.jsp]],名称为&#39; mvc-dispatcher&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean的缓存实例&#39; requestDataValueProcessor&#39; 09:01:22.190 [http-8080-4] DEBUG o.s.web.servlet.view.JstlView - 转发到InternalResourceView资源[/WEB-INF/pages/login.jsp]&#39; login&#39; 09:01:22.279 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。 09:01:22.279 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - 已成功完成请求 09:01:22.279 [http-8080-4] DEBUG o.s.s.w.a.ExceptionTranslationFilter - 正常处理链 09:01:22.280 [http-8080-4] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成 09:01:23.967 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - / j_spring_security_check位于第1位,共11个额外的过滤链;触发过滤器:&#39; SecurityContextPersistenceFilter&#39; 09:01:23.967 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession为SPRING_SECURITY_CONTEXT返回了null对象 09:01:23.968 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - 没有来自HttpSession的SecurityContext:org.apache.catalina.session.StandardSessionFacade@48842f5e。将创建一个新的。 09:01:23.968 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - / j_spring_security_check位于第2位的11位额外的过滤链;烧制过滤器:&#39; CsrfFilter&#39; 09:01:23.969 [http-8080-4] DEBUG o.s.security.web.csrf.CsrfFilter - 为http://localhost:8080/EmployeeManagement/j_spring_security_check找到无效的CSRF令牌 09:01:23.971 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - 名称为&#39; mvc-dispatcher&#39;的DispatcherServlet处理[/ EmployeeManagement / 403]的POST请求 09:01:23.971 [http-8080-4] DEBUG o.s.w.s.m.a.DefaultAnnotationHandlerMapping - 使用处理程序[com.employeemgmt.controller.EmployeeController@18ba5047]和1个拦截器将[/ 403]映射到HandlerExecutionChain 09:01:23.982 [http-8080-4] DEBUG o.s.w.s.m.a.AnnotationMethodHandlerExceptionResolver - 解决处理程序中的异常[com.employeemgmt.controller.EmployeeController@18ba5047]:org.springframework.web.HttpRequestMethodNotSupportedException:请求方法&#39; POST&#39;不支持 09:01:23.984 [http-8080-4] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - 解决处理程序中的异常[com.employeemgmt.controller.EmployeeController@18ba5047]:org.springframework.web.HttpRequestMethodNotSupportedException:请求方法&#39; POST&#39;不支持 09:01:23.984 [http-8080-4] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - 解决处理程序中的异常[com.employeemgmt.controller.EmployeeController@18ba5047]:org.springframework.web.HttpRequestMethodNotSupportedException:请求方法&#39; POST&#39;不支持 09:01:23.984 [http-8080-4]警告o.s.web.servlet.PageNotFound - 请求方法&#39; POST&#39;不支持 09:01:23.984 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。 09:01:23.984 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView返回DispatcherServlet,其名称为&#39; mvc-dispatcher&#39;:假设HandlerAdapter已完成请求处理 09:01:23.984 [http-8080-4] DEBUG o.s.web.servlet.DispatcherServlet - 已成功完成请求 09:01:23.984 [http-8080-4] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。 09:01:23.984 [http-8080-4] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成
答案 0 :(得分:0)
您的控制器方法使用RequestMethod.GET进行注释,而login.jsp表单方法正在请求POST。两者都应该是POST。
答案 1 :(得分:0)
我在这里添加了OP找到的答案。
csrf令牌值未被替换。我添加了 -
<%@ page isELIgnored ="false" %>
Personnaly我通过在spring-security中删除csrf解决了这个问题。在http
代码集<csrf disabled="true"/>
答案 2 :(得分:0)
您在控制器中的GET
映射上使用/login
方法。
使用
POST
方法进行身份验证是标准的。
将@RequestMapping(value = "/login", method = RequestMethod.GET)
更改为
@RequestMapping(value = "/login", method = RequestMethod.POST)