springboot自定义注解进行登录权限的验证
本人以前没有写过这种的拦截,经过查资料和收集前辈们的经验,自己实现后的一些心得想分享给大家,希望大家不喜勿喷.
这里涉及到拦截器,先简单的说明一下拦截器:
拦截器在我们项目中经常使用,最简单 的就是用来判断是否登录.要实现拦截器需要完成两个步骤.
1.创建我们自己的拦截器类并且实现HandlerInterceptor接口 或者HandlerInterceptorAdapter类
2.重写preHandle方法(简单的解释一下拦截器方法的执行顺序)
我们可以在这个方法里面加上我们自己的逻辑,比如判断他是否已经登录
如果被我们拦截以后,不能通过的,请求,我们可以这样编写返回值
这两步做完以后,我们只是创建了一个自己的拦截器,但是我们需要把他加到springboot的拦截器中,这时我们需要创建一个配置类,用于把我们自己的拦截器注册到Springboot中,实现WebMvcConfigurer
并且重写addInterceptors方法,
简单解释一下, addInterceptor 中添加自己创建的拦截器,addPathPatterns表示要拦截的请求路径,addPathPatterns("/**")对所有请求都拦截,excludePathPatterns表示要排除的请求路径
下面是WebMvcConfigurer 常重写的方法和注解:
一般我们通过创建一个自定义的注解,来配置我们的请求,列如,我们的请求方法上有我们定义的注解需要进行登录,没有的不需要(其实我们上面的拦截器也能做到这一点).判断是否有注解需要在我们定义的拦截器中判断.
自定义注解只需要一步:
就这样,其实我们一般都需要拦截器+注解来相互配合,通过查找请求的路径是否存在该注解来进行判断
注解的解释:
@Target 注解
@Retention 注解
@Inherited(可以不用)
@Documented
上面就是,我们可以通过自定义注解来拦截请求,查看是否需要登录的整体思路
下面试具体代码
注解类:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 登录权限的注解
* @author Administrator
*
*/
@Target(value = { ElementType.TYPE,ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginInterceptor {
}
创建自己的拦截器类:
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.cpp.epsserv.config.RedisClient;
import com.cpp.epsserv.config.SpringContextUtil;
import com.cpp.epsserv.encapsulation.whcgpt.getData.SignUtils;
import com.cpp.epsserv.mapper.IntLoginMapper;
import com.cpp.epsserv.model.IntLogin;
import com.cpp.epsserv.model.IntLoginExample;
public class SecurityInterceptor extends HandlerInterceptorAdapter {
//参数签名认证信息(具体使用签名认证)
private String httpHeaderSign = "sign";
//用户名称
private String httpHeaderName = "username";
//鉴权失败后返回的HTTP错误码,默认为401
private int unauthorizedErrorCode = HttpServletResponse.SC_UNAUTHORIZED;
// 获取到redis
private static RedisClient redisClient = SpringContextUtil.getBean(RedisClient.class);
private static IntLoginMapper loginMapper = SpringContextUtil.getBean(IntLoginMapper.class);
//在调用方法之前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//将handler强转化为handlermethod
HandlerMethod handlerMethod = (HandlerMethod)handler;
//从方法处理器中获取要调用的方法
Method method = handlerMethod.getMethod();
//获取方法上的LoginInterceptor注解
LoginInterceptor loginInterceptor = method.getAnnotation(LoginInterceptor.class);
if (null == loginInterceptor) {
//如果注解为null,说明此方法没有注解直接放过
return true;
}
//从请求头中获取验证信息
String sign = request.getHeader(httpHeaderSign);
String username = request.getHeader(httpHeaderName);
IntLoginExample example = new IntLoginExample();
example.createCriteria().andUsernameEqualTo(username);
List
if (null == loginList || loginList.size()<0) {
JSONObject jsonObject = new JSONObject();
PrintWriter out = null;
try {
response.setStatus(unauthorizedErrorCode);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
jsonObject.put("code", response.getStatus());
jsonObject.put("failreason", "登录账号或密码错误");
out = response.getWriter();
out.println(jsonObject);
return false;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (null != out) {
out.flush();
out.close();
}
}
}
ServletInputStream inputStream = request.getInputStream();
String jsonString = IOUtils.toString(inputStream);
Map
if (null == mapMembers || mapMembers.isEmpty()) {
JSONObject jsonObject = new JSONObject();
PrintWriter out = null;
try {
response.setStatus(unauthorizedErrorCode);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
jsonObject.put("code", response.getStatus());
jsonObject.put("failreason", "登录超时,请重新登录");
out = response.getWriter();
out.println(jsonObject);
return false;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (null != out) {
out.flush();
out.close();
}
}
}
String token = String.valueOf(mapMembers.get("token"));
String localSign = SignUtils.Sign(token+jsonString,loginList.get(0).getPassword());
if (!localSign.equals(sign)) {
JSONObject jsonObject = new JSONObject();
PrintWriter out = null;
try {
response.setStatus(unauthorizedErrorCode);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
jsonObject.put("code", response.getStatus());
jsonObject.put("failreason", "登录验证信息有误");
out = response.getWriter();
out.println(jsonObject);
return false;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (null != out) {
out.flush();
out.close();
}
}
}
return true;
}
}
将我们自定义的拦截器加到springmvc的拦截器中(拦截器是依赖于web框架的)
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 拦截器:判断是否登录
* @author Administrator
*
*/
@Configuration
public class WebAppConfiguration extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/**");
}
}
2019/01/14 10:25