spring boot 配置拦截器验证使用 token 登录


1、自定义登录注解

package io.xiongdi.annotation; import java.lang.annotation.*; /** * @author wujiaxing * @date 2019-07-12 * 登录校验 */ @Target(ElementType.METHOD) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Login { }

 

2、创建 token 实体类

package io.xiongdi.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Builder; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 用户token * @author wujiaxing * @date ${2019-6-30} */ @Data @TableName("tb_token") @Builder public class TokenEntity implements Serializable { private static final long serialVersionUID = 5584132314624077161L; public TokenEntity(){} public TokenEntity(long userId, String token, LocalDateTime expireTime, LocalDateTime updateTime) { this.userId = userId; this.token = token; this.expireTime = expireTime; this.updateTime = updateTime; } /** * 用户ID */ @TableId(type = IdType.INPUT) private long userId; /** * token */
    private String token; /** * 过期时间 */
    private LocalDateTime expireTime; /** * 修改时间 */
    private LocalDateTime updateTime; }

 

3、创建处理 token 的接口方法

package io.xiongdi.service; import com.baomidou.mybatisplus.extension.service.IService; import io.xiongdi.entity.TokenEntity; /** * token * @author wujiaxing * @date 2019-06-30 */
public interface TokenService extends IService<TokenEntity> { /** * <p> * 根据请求token查询token信息 * </p> * @param token * @return
     */ TokenEntity queryByToken(String token); /** * 创建token * @param userId 用户ID * @return 返回token信息 */ TokenEntity createToken(long userId); /** * 设置token过期 * @param userId 用户ID */
    void expireToken(long userId); }
package io.xiongdi.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import io.xiongdi.dao.TokenDao; import io.xiongdi.entity.TokenEntity; import io.xiongdi.service.TokenService; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Date; import java.util.UUID; /** * @author wujiaxing * @date 2019-07-08 */ @Service("tokenService") public class TokenServiceImpl extends ServiceImpl<TokenDao, TokenEntity> implements TokenService { /** * 12 小时过期 单位:毫秒 */
    private final static int EXPIRE = 3600 * 12 * 1000; /** * 根据请求头的token查询数据库对应的token信息 * @param token * @return
     */ @Override public TokenEntity queryByToken(String token) { return this.getOne(new QueryWrapper<TokenEntity>().eq("token", token)); } @Override public TokenEntity createToken(long userId) { // 得到当前时间
        LocalDateTime now = LocalDateTime.now(); // 根据过期时间加上当前时间,得到token的有效期
        long indate = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() + EXPIRE; LocalDateTime tokenExpireDateTime = LocalDateTime.ofInstant(new Date(indate).toInstant(), ZoneId.systemDefault()); // 生成token
        String token = generateToken(); // 创建实体对象
        TokenEntity tokenEntity = TokenEntity.builder().expireTime(tokenExpireDateTime).userId(userId).token(token).updateTime(now).build(); // 放入数据库保存
        this.saveOrUpdate(tokenEntity); return tokenEntity; } /** * 生成token * @return
     */
    private String generateToken() { return UUID.randomUUID().toString().replace("-", ""); } @Override public void expireToken(long userId) { // 获取当前时间
        LocalDateTime now = LocalDateTime.now(); TokenEntity tokenEntity = TokenEntity.builder().userId(userId).expireTime(now).updateTime(now).build(); this.saveOrUpdate(tokenEntity); } }

 

4、创建拦截器

package io.xiongdi.interceptor; import io.xiongdi.annotation.Login; import io.xiongdi.common.exception.XDException; import io.xiongdi.common.utils.ResultType; import io.xiongdi.entity.TokenEntity; import io.xiongdi.service.TokenService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.LocalDateTime; /** * 权限(token)验证 * @author wujiaxing * @date 2019-06-30 */ @Component public class AuthorizationInterceptor implements HandlerInterceptor { @Autowired private TokenService tokenService; public final static String USER_KEY = "userId"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Login annotation; // 如果处理对象是一个处理方法,则获取到方法上的注解
        if (handler instanceof HandlerMethod) { annotation = ((HandlerMethod)handler).getMethodAnnotation(Login.class); // 否则直接放过拦截的请求
        } else { return true; } // 说明此方法没有Login注解
        if (annotation == null) { return true; } // 从请求头获取token
        String token = request.getHeader("token"); // 如果请求头没有token,则从请求参数中取
        if (StringUtils.isBlank(token)) { token = request.getParameter("token"); } // 如果还是没有token,则抛异常
        if (StringUtils.isBlank(token)) { throw new XDException(ResultType.TOKEN_NULL); } // 查询token信息
        TokenEntity tokenEntity = tokenService.queryByToken(token); // 如果token信息是否为null或是否过期,则抛异常
        if (tokenEntity == null || tokenEntity.getExpireTime().isBefore(LocalDateTime.now())) { throw new XDException(ResultType.TOKEN_EXPIRE); } // 否则,存入request作用域,后续根据userId,获取用户信息
 request.setAttribute(USER_KEY, tokenEntity.getUserId()); return true; } }

 

5、将拦截器配置给 spring boot

package io.xiongdi.config; import io.xiongdi.interceptor.AuthorizationInterceptor; import io.xiongdi.resolver.LoginUserHandlerMethodArgumentResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; /** * @author wujiaxing * <p> * 此配置类可配置拦截器、参数解析器、返回值解析器、跨域支持等等 * </p> */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private AuthorizationInterceptor authorizationInterceptor; @Autowired private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; /** * 拦截器配置 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authorizationInterceptor).addPathPatterns("/api/**"); } /** * 跨域支持配置 * @param registry */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowCredentials(true).allowedOrigins("*").allowedMethods("GET", "PUT", "DELETE", "POST", "OPTIONS").maxAge(3600); } /** * 参数解析配置 * @param resolvers */ @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(loginUserHandlerMethodArgumentResolver); } }

 

6、配置已经好了,可以开始测试


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM