add custom session, permission
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package me.hatter.sample.common;
|
||||
|
||||
import me.hatter.sample.common.interceptor.CustomHandlerInterceptorAdapter;
|
||||
import me.hatter.sample.common.resolver.CustomSessionArgumentResolver;
|
||||
import me.hatter.sample.common.resolver.SystemTimeArgumentResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -14,8 +16,20 @@ public class WebConfig extends WebMvcConfigurerAdapter {
|
||||
@Autowired
|
||||
SystemTimeArgumentResolver systemTimeArgumentResolver;
|
||||
|
||||
@Autowired
|
||||
CustomSessionArgumentResolver customSessionArgumentResolver;
|
||||
|
||||
@Autowired
|
||||
CustomHandlerInterceptorAdapter customHandlerInterceptorAdapter;
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(systemTimeArgumentResolver);
|
||||
argumentResolvers.add(customSessionArgumentResolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(customHandlerInterceptorAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package me.hatter.sample.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Permission {
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package me.hatter.sample.common.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import me.hatter.sample.common.message.ErrorMessageException;
|
||||
import me.hatter.tools.commons.exception.ExceptionUtil;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ControllerAdvice
|
||||
public class GlobalControllerExceptionHandler {
|
||||
|
||||
@ResponseBody
|
||||
// @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "internal error")
|
||||
@ExceptionHandler(Throwable.class)
|
||||
public void handleException(HttpServletResponse response, Throwable t) throws IOException {
|
||||
if (t instanceof ErrorMessageException) {
|
||||
response.setStatus(((ErrorMessageException) t).getStatusCode());
|
||||
response.getWriter().write(JSON.toJSONString(((ErrorMessageException) t).getErrorMessage(), true));
|
||||
} else {
|
||||
final Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("stacktrace", ExceptionUtil.printStackTrace(t));
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.getWriter().write(JSON.toJSONString(result, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package me.hatter.sample.common.interceptor;
|
||||
|
||||
import me.hatter.sample.common.annotation.Permission;
|
||||
import me.hatter.sample.common.message.ErrorMessage;
|
||||
import org.springframework.boot.autoconfigure.web.BasicErrorController;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class CustomHandlerInterceptorAdapter extends HandlerInterceptorAdapter {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
System.out.println("[CustomHandlerInterceptorAdapter] " + handler.getClass());
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
throw new IllegalArgumentException("Not supported handler: " + handler.getClass());
|
||||
}
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
|
||||
// ignore error controller
|
||||
if (handlerMethod.getMethod().getDeclaringClass().equals(BasicErrorController.class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
|
||||
//
|
||||
// RequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
// DefaultErrorAttributes errorAttributes = new DefaultErrorAttributes();
|
||||
// Map<String, Object> attributes = errorAttributes.getErrorAttributes(requestAttributes, true);
|
||||
|
||||
Permission p = handlerMethod.getMethodAnnotation(Permission.class);
|
||||
if (p == null) {
|
||||
throw new ErrorMessage("permission_denied",
|
||||
"No permission: " + request.getRequestURI()
|
||||
).ex(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package me.hatter.sample.common.message;
|
||||
|
||||
public class ErrorMessage {
|
||||
private String error;
|
||||
private String error_description;
|
||||
|
||||
public ErrorMessage() {
|
||||
}
|
||||
|
||||
public ErrorMessage(String error, String error_description) {
|
||||
this.error = error;
|
||||
this.error_description = error_description;
|
||||
}
|
||||
|
||||
public ErrorMessageException ex(int statusCode) {
|
||||
return new ErrorMessageException(statusCode, this);
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getError_description() {
|
||||
return error_description;
|
||||
}
|
||||
|
||||
public void setError_description(String error_description) {
|
||||
this.error_description = error_description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package me.hatter.sample.common.message;
|
||||
|
||||
public class ErrorMessageException extends RuntimeException {
|
||||
private final int statusCode;
|
||||
private final ErrorMessage errorMessage;
|
||||
|
||||
public ErrorMessageException(int statusCode, ErrorMessage errorMessage) {
|
||||
this.statusCode = statusCode;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public ErrorMessage getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package me.hatter.sample.common.resolver;
|
||||
|
||||
import me.hatter.sample.common.session.CustomSession;
|
||||
import me.hatter.tools.commons.security.random.RandomTool;
|
||||
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class CustomSessionArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.getParameterType().equals(CustomSession.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
final HttpServletRequest httpServletRequest = (HttpServletRequest) webRequest.getNativeRequest();
|
||||
final HttpServletResponse httpServletResponse = (HttpServletResponse) webRequest.getNativeResponse();
|
||||
Cookie cookie = WebUtils.getCookie(httpServletRequest, "hatter_session_id");
|
||||
if (cookie == null) {
|
||||
cookie = new Cookie("hatter_session_id", RandomTool.secureRandom().nextBytes(64).asBase58());
|
||||
cookie.setPath("/");
|
||||
cookie.setHttpOnly(true);
|
||||
httpServletResponse.addCookie(cookie);
|
||||
}
|
||||
final String prefix = cookie.getValue();
|
||||
return new CustomSession(prefix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package me.hatter.sample.common.session;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class CustomSession {
|
||||
private static final ConcurrentMap<String, Object> cache = new ConcurrentHashMap<>();
|
||||
private final String prefix;
|
||||
|
||||
public CustomSession(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void put(String key, Object value) {
|
||||
cache.put(prefix + ":" + key, value);
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
return cache.get(prefix + ":" + key);
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package me.hatter.sample.web.controller;
|
||||
|
||||
import me.hatter.sample.common.annotation.Permission;
|
||||
import me.hatter.sample.common.annotation.SystemTime;
|
||||
import me.hatter.sample.common.session.CustomSession;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -9,9 +11,34 @@ import java.util.Date;
|
||||
@RestController
|
||||
public class SampleController {
|
||||
|
||||
@Permission
|
||||
@GetMapping("/")
|
||||
public String home(
|
||||
@SystemTime Date time) {
|
||||
return "Hello, World: " + time;
|
||||
}
|
||||
|
||||
@Permission
|
||||
@GetMapping("/exception")
|
||||
public String exception() {
|
||||
throw new RuntimeException("error");
|
||||
}
|
||||
|
||||
@GetMapping("/nopermission")
|
||||
public String noPermission() {
|
||||
return "Hello, World!";
|
||||
}
|
||||
|
||||
@Permission
|
||||
@GetMapping("/count")
|
||||
public String count(CustomSession session) {
|
||||
final Object c = session.get("count");
|
||||
int count = 0;
|
||||
if (c != null) {
|
||||
count = (Integer) c;
|
||||
count++;
|
||||
}
|
||||
session.put("count", count);
|
||||
return "Count @" + session.getSessionId() + " : " + count;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user