- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在编写一个 Java Spring MVC 4 REST 应用程序,它将位于前端设备(网站、移动应用程序等)和数据库之间。我有下面的代码,将为每个请求创建一个新 session (因为 REST 是无状态的),查看请求的授权 header ,并确认 token 有效并且请求已通过身份验证。
当用户在没有有效 token 的情况下请求安全方法时,我希望将未经授权的请求从 500 Access Is Denied 消息重定向到 401 Unauthorized 消息。
这就是我目前所拥有的。
拒绝访问处理程序:
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;
}
}
最后是 Controller :
@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 header 的情况下运行该方法时,我得到了这个错误(而不是我想要得到的错误):
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
我不知道为什么我无法获得返回 401 或 500 以外的任何其他状态代码的未授权请求。
你怎么看?
最佳答案
好吧,我无法从社区获得任何帮助,但我确实找到了解决方案——尽管这不是直接的解决方案。
@ControllerAdvice
public class SecurityExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({AccessDeniedException.class})
public ResponseEntity<Object> handleAccessDeniedException(Exception ex, WebRequest request) {
if(ex.getMessage().toLowerCase().indexOf("access is denied") > -1) {
return new ResponseEntity<Object>("Unauthorized Access", new HttpHeaders(), HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity<Object>(ex.getMessage(), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
我的应用程序中的这个新文件将允许我控制异常期间发生的事情。现在我可以手动检查问题,看看它是否是“访问被拒绝”,然后重定向到 401,这确实有效。上面的问题是重定向到 401 的代码从未被命中。这段代码确实被执行了。
同样,这不是一个直接的解决方案,因为我们正在操纵不同的 Spring MVC 部分和某种黑客默认行为以使其工作。
如果有人有更优雅的解决方案,请发帖。
关于java - 对于@PreAuthorized unauth 请求,收到 Spring MVC AccessDeniedException 500 错误而不是自定义 401 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43554489/
这个问题已经有答案了: Avoid Java 8 Files.walk(..) termination cause of ( java.nio.file.AccessDeniedException )
我正在尝试删除一个文件,然后重新创建它。首先,我检查该文件是否已存在,如果存在,则将其删除。然后我尝试在同一位置创建一个具有相同名称的新文件。当我这样做时,我收到此错误: java.nio.file.
这是尝试在我的 usb 连接的 android 设备上运行/测试应用程序后我的 android studio 控制台收到的错误 错误:任务 ':app:mockableAndroidJar' 执行失败
我正在创建简单的对象序列化,并且BufferedOutputStream的创建引发了异常AccessDeniedException。这是代码: Path filePath = Paths.get("c
我想访问我的网络应用程序之外的静态资源,这样它们就不会在每次重新部署时被破坏,但我似乎无法获取它们 我有一个 servlet,旨在通过 FileOutputStream 提供这些图像,但当我将其部署到
描述: 我在 Java 8 中创建了一个 ZIP 文件,并尝试将一个目录及其所有子文件和目录复制到该 zip 文件中。 Path directory = Paths.get("P:\Java\T
在我的 Spring Boot Web 应用程序中,只要用户没有必要的权限,我就会在我的业务代码中抛出 org.springframework.security.access.AccessDenied
我有 2 个服务:RecentRecordService 和 BookService。 @Service public class RecentRecordService { @Transac
我正在使用 Swift AWS Mobile Hub Helper 构建我的 iOS 应用程序并连接到我的 DynamoDB 数据库。我可以看到,在使用 Facebook SignInProvider
我使用这个自定义错误处理程序: @Component public class OAuth2AuthenticationEntryPoint implements AuthenticationEntr
使用AWS CLI aws --version aws-cli/1.11.21 Python/2.7.12 Darwin/15.3.0 botocore/1.4.78 如https://github.
解决完所有authentication related problems后在我的第一个 Spring Web 应用程序中,我现在陷入了授权的困境。 使用@Secured注释进行配置非常简单,所以我认为
我在 Spring Security 中使用角色层次结构。 ROLE_USER > ROLE_GUEST
我编写了一个小方法,用于告诉我应用程序的另一个实例是否已在运行。我知道有很多方法可以查明另一个实例是否正在运行,但我选择了这个。我正在创建一个空文件并在应用程序实例期间保持锁定状态。如果另一个实例正在
我是 amazon Dynamo DB 的新手。我收到访问被拒绝的异常。 请帮我解决这个问题。 错误: User: arn:aws:sts::xx:assumed-role/Cognito_Sampl
我在解决运行在 Tomcat 6.0 上的 Java Servlet 的权限问题时遇到了问题 当我尝试操作存储在网络共享上的文件时遇到 AccessDeniedException。 这是堆栈跟踪: j
我目前正在尝试将 GWT 网络应用程序部署到 tomcat 实例,但该程序未正确运行。仔细检查 tomcat 日志后,Tomcat 似乎遇到了 AccessDeniedException。 SEVER
我想使用此代码读取文件内容: String content = new String(Files.readAllBytes(Paths.get("/sys/devices/virtual/dmi/id
我是 AWS 新手。我有一个用户帐户和两个角色,一个用于生产,一个用于测试。 通常我会登录我的帐户并切换到产品角色来运行一些简单的选择查询。 现在我想通过 PyAthena 在 Python 中本地使
首先让我说,对于我的场景,访问应该被拒绝。内置 Spring Boot 和 Spring Security 4。我允许任何人连接到 websocket 并订阅一个主题,但我确保能够使用以下 web 套
我是一名优秀的程序员,十分优秀!