add custom session, permission
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package me.hatter.sample.common;
|
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 me.hatter.sample.common.resolver.SystemTimeArgumentResolver;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -14,8 +16,20 @@ public class WebConfig extends WebMvcConfigurerAdapter {
|
|||||||
@Autowired
|
@Autowired
|
||||||
SystemTimeArgumentResolver systemTimeArgumentResolver;
|
SystemTimeArgumentResolver systemTimeArgumentResolver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CustomSessionArgumentResolver customSessionArgumentResolver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CustomHandlerInterceptorAdapter customHandlerInterceptorAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||||
argumentResolvers.add(systemTimeArgumentResolver);
|
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;
|
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.annotation.SystemTime;
|
||||||
|
import me.hatter.sample.common.session.CustomSession;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -9,9 +11,34 @@ import java.util.Date;
|
|||||||
@RestController
|
@RestController
|
||||||
public class SampleController {
|
public class SampleController {
|
||||||
|
|
||||||
|
@Permission
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public String home(
|
public String home(
|
||||||
@SystemTime Date time) {
|
@SystemTime Date time) {
|
||||||
return "Hello, World: " + 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