我正在寫一個Java Spring MVC的REST 4的應用程序,將前端設備(網站,移動應用等)和數據庫之間坐。我有下面的代碼,將爲每個請求創建一個新的會話(因爲REST是無狀態的),請查看請求的授權標頭,並確認令牌有效並請求驗證。Spring MVC的AccessDeniedException異常的500錯誤,而不是自定義401錯誤@PreAuthorized未授權的請求
當用戶請求一個安全的方法,沒有有效的令牌,我在尋找未授權的請求從500周重定向的訪問被拒絕的消息到401未授權消息。
這是我到目前爲止。
AccessDeniedHandler:
public class Unauthorized401AccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException)
throws IOException, ServletException {
response.setStatus(401);
}
}
WebSecurityConfigurerAdapter:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.accessDeniedHandler(new Unauthorized401AccessDeniedHandler());
}
}
篩選:
public class SecurityFilter implements Filter {
final static Logger logger = Logger.getLogger(SecurityFilter.class);
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession();
String requestUri = request.getRequestURI();
session.invalidate();
SecurityContextHolder.clearContext();
session = request.getSession(true); // create a new session
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
boolean isLoggedIn = false;
String token = null;
String authorizationHeader = request.getHeader("authorization");
if(authorizationHeader != null && authorizationHeader.startsWith("bearer")) {
String encryptedToken = authorizationHeader.split(" ")[1];
token = StringUtils.newStringUtf8(Base64.decodeBase64(encryptedToken));
// confirm user is logged in and authorized here TBD
isLoggedIn = true;
}
PreAuthenticatedAuthenticationToken authentication = null;
if(isLoggedIn) {
SessionCredentialsModel authRequestModel = new SessionCredentialsModel();
authRequestModel.employeeId = 323;
authRequestModel.firstName = "Danny";
authRequestModel.lastName = "Boy";
authRequestModel.token = "this_is_a_test_token";
authentication = new PreAuthenticatedAuthenticationToken(authRequestModel, token);
} else {
authentication = new PreAuthenticatedAuthenticationToken(new SessionCredentialsModel(), null);
}
authentication.setAuthenticated(true);
ctx.setAuthentication(authentication);
SecurityContextHolder.setContext(ctx);
chain.doFilter(req, res);
}
安全模型(又名安全上下文校長):
public class SessionCredentialsModel {
public int employeeId;
public String firstName;
public String lastName;
public String token;
public boolean isAuthenticated() {
if(employeeId > 0 && token != null) {
return true;
}
return false;
}
}
終於控制器:
@RequestMapping(value = "/", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("principal.isAuthenticated()")
public ResponseEntity<LoginResponseModel> create() {
LoginResponseModel responseModel = new LoginResponseModel();
responseModel.statusCode = 55;
responseModel.token = "authorized model worked!";
return new ResponseEntity<LoginResponseModel>(responseModel, HttpStatus.OK);
}
當我運行的方法,無需Authorization頭我得到這個錯誤(而不是我希望得到錯誤):
HTTP Status 500 - Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
type Exception report
message Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
net.pacificentertainment.middletier.app.security.SecurityFilter.doFilter(SecurityFilter.java:73)
root cause
org.springframework.security.access.AccessDeniedException: Access is denied
org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
net.pacificentertainment.middletier.app.controllers.EmployeeController$$EnhancerBySpringCGLIB$$b6765b64.create(<generated>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
net.pacificentertainment.middletier.app.security.SecurityFilter.doFilter(SecurityFilter.java:73)
note The full stack trace of the root cause is available in the Apache Tomcat/8.0.43 logs.
Apache Tomcat/8.0.43
我m,在虧損弄清楚爲什麼我不能讓未經授權的請求返回一個401 - 超過500
你認爲其他或任何其他狀態代碼?
它被解決了幾次例如:http://stackoverflow.com/a/22785514/4053082 –