springmvc自定义注解拦截器方式实现注解功能拦截器的配置

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a975261294/article/details/73277715

注解类:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenRequiresRoles {
	
    /**
     * A single String role name or multiple comma-delimitted role names required in order for the method
     * invocation to be allowed.
     */
    String[] value();

}

使用拦截器的方式:

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.google.gson.Gson;
import com.heiman.smarthome.po.custom.Config;
import com.heiman.smarthome.po.custom.Error;
import com.heiman.smarthome.utils.JWTEncodeAndDecode;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.SignatureException;

/**
 * @Description : 从token中获取用户拥有的角色,和链接需要的角色作比较, 如果缺少角色,则禁止访问该链接,并返回错误码和错误信息
 */
public class TokenAnnotationInterceptor extends HandlerInterceptorAdapter {

	@Autowired
	private Config config;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		// 检查用户是否拥有权限
		return checkRole(request, response, handler);
	}

	/**
	 * 检查被注解的类是否拥有权限
	 * 
	 * @param request
	 * @param response
	 * @param handler
	 * @return
	 */
	public boolean checkRole(HttpServletRequest request, HttpServletResponse response, Object handler) {

		String header = request.getHeader("Access-Token");
		Gson gson = new Gson();

		if (handler instanceof HandlerMethod) {
			HandlerMethod hm = (HandlerMethod) handler;
			Class<?> clazz = hm.getBeanType();
			Method m = hm.getMethod();
			try {
				if (clazz != null && m != null) {
					// 检查类和方法是否有注解
					boolean isClzAnnotation = clazz.isAnnotationPresent(TokenRequiresRoles.class);
					boolean isMethondAnnotation = m.isAnnotationPresent(TokenRequiresRoles.class);
					TokenRequiresRoles rc = null;

					// 如果方法和类声明中同时存在这个注解,那么方法中的会覆盖类中的设定。
					if (isMethondAnnotation) {
						rc = m.getAnnotation(TokenRequiresRoles.class);
					} else if (isClzAnnotation) {
						rc = clazz.getAnnotation(TokenRequiresRoles.class);
					}

					// 注解中需要的角色
					String[] value = rc.value();
					List<String> requireRole = new ArrayList<String>();
					Collections.addAll(requireRole, value);

					// 解码token获取角色
					Claims decode = JWTEncodeAndDecode.decode(header);
					String[] roles = JWTEncodeAndDecode.getRoles(decode);
					List<String> tokenRole = new ArrayList<String>();
					Collections.addAll(tokenRole, roles);

					// 进行角色访问的权限控制,只有当前用户是需要的角色才予以访问。
					boolean isEquals = tokenRole.containsAll(requireRole);

					if (!isEquals) {
						// 未授权访问
						Error error = new Error(434627, "Unauthorized access");
						response.getWriter().write(gson.toJson(error));
						return false;
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				if (config.printError())
					e.printStackTrace();
			}
		}

		return true;
	}

}
springmvc中配置拦截器:

	<!-- 拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
			<mvc:mapping path="/v1/**" />
			<mvc:mapping path="/v2/**" />
			<!-- 拦截器类 -->
			<bean
				class="com.heiman.smarthome.spring.annotation.TokenAnnotationInterceptor"></bean>
		</mvc:interceptor>
		<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
	</mvc:interceptors>






展开阅读全文

没有更多推荐了,返回首页