Commit 29076e80 by fengshuonan

删除rest模块

parent cef3257b
...@@ -2,7 +2,6 @@ package com.stylefeng.guns.core.util; ...@@ -2,7 +2,6 @@ package com.stylefeng.guns.core.util;
import com.stylefeng.guns.core.common.constant.JwtConstants; import com.stylefeng.guns.core.common.constant.JwtConstants;
import io.jsonwebtoken.*; import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
...@@ -24,7 +23,6 @@ import java.util.Map; ...@@ -24,7 +23,6 @@ import java.util.Map;
* @author fengshuonan * @author fengshuonan
* @Date 2017/8/25 10:59 * @Date 2017/8/25 10:59
*/ */
@Component
public class JwtTokenUtil { public class JwtTokenUtil {
/** /**
......
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50721
Source Host : localhost:3306
Source Schema : guns_rest
Target Server Type : MySQL
Target Server Version : 50721
File Encoding : 65001
Date: 26/01/2018 21:16:47
*/
DROP DATABASE IF EXISTS guns_rest;
CREATE DATABASE IF NOT EXISTS guns_rest DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin');
SET FOREIGN_KEY_CHECKS = 1;
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stylefeng.guns</groupId>
<artifactId>guns-rest</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>guns-rest</name>
<description>guns REST服务器</description>
<parent>
<groupId>com.stylefeng</groupId>
<artifactId>guns-parent</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.stylefeng</groupId>
<artifactId>guns-core</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.stylefeng.guns.rest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GunsRestApplication {
public static void main(String[] args) {
SpringApplication.run(GunsRestApplication.class, args);
}
}
package com.stylefeng.guns.rest;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* Guns REST Web程序启动类
*
* @author fengshuonan
* @date 2017年9月29日09:00:42
*/
public class GunsRestServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(GunsRestApplication.class);
}
}
package com.stylefeng.guns.rest.common;
/**
* 测试用的
*
* @author fengshuonan
* @date 2017-08-25 16:47
*/
public class SimpleObject {
private String user;
private String name;
private String tips;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTips() {
return tips;
}
public void setTips(String tips) {
this.tips = tips;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
package com.stylefeng.guns.rest.common.aop;
import com.stylefeng.guns.core.aop.BaseControllerExceptionHandler;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
import io.jsonwebtoken.JwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
*
* @author fengshuonan
* @date 2016年11月12日 下午3:19:56
*/
@ControllerAdvice
public class GlobalExceptionHandler extends BaseControllerExceptionHandler {
private Logger log = LoggerFactory.getLogger(this.getClass());
/**
* 拦截jwt相关异常
*/
@ExceptionHandler(JwtException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorTip jwtException(JwtException e) {
return new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage());
}
}
package com.stylefeng.guns.rest.common.exception;
import com.stylefeng.guns.core.exception.ServiceExceptionEnum;
/**
* 所有业务异常的枚举
*
* @author fengshuonan
* @date 2016年11月12日 下午5:04:51
*/
public enum BizExceptionEnum implements ServiceExceptionEnum {
/**
* token异常
*/
TOKEN_EXPIRED(700, "token过期"),
TOKEN_ERROR(700, "token验证失败"),
/**
* 签名异常
*/
SIGN_ERROR(700, "签名验证失败"),
/**
* 其他
*/
AUTH_REQUEST_ERROR(400, "账号密码错误");
BizExceptionEnum(int code, String message) {
this.code = code;
this.message = message;
}
private Integer code;
private String message;
@Override
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.stylefeng.guns.rest.common.persistence.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.rest.common.persistence.model.User;
/**
* <p>
* Mapper 接口
* </p>
*
* @author stylefeng
* @since 2017-08-23
*/
public interface UserMapper extends BaseMapper<User> {
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.rest.common.persistence.dao.UserMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.stylefeng.guns.rest.common.persistence.model.User">
<id column="id" property="id" />
<result column="userName" property="userName" />
</resultMap>
</mapper>
package com.stylefeng.guns.rest.common.persistence.model;
import com.baomidou.mybatisplus.activerecord.Model;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author stylefeng
* @since 2017-08-23
*/
public class User extends Model<User> {
private static final long serialVersionUID = 1L;
private Long id;
private String userName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
protected Serializable pkVal() {
return this.id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName=" + userName +
"}";
}
}
package com.stylefeng.guns.rest.config;
import com.stylefeng.guns.core.config.DefaultFastjsonConfig;
import com.stylefeng.guns.rest.config.properties.RestProperties;
import com.stylefeng.guns.rest.modular.auth.converter.WithSignMessageConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 签名校验messageConverter
*
* @author fengshuonan
* @date 2017-08-25 16:04
*/
@Configuration
public class MessageConverConfig {
@Bean
@ConditionalOnProperty(prefix = RestProperties.REST_PREFIX, name = "sign-open", havingValue = "true", matchIfMissing = true)
public WithSignMessageConverter withSignMessageConverter() {
WithSignMessageConverter withSignMessageConverter = new WithSignMessageConverter();
DefaultFastjsonConfig defaultFastjsonConfig = new DefaultFastjsonConfig();
withSignMessageConverter.setFastJsonConfig(defaultFastjsonConfig.fastjsonConfig());
withSignMessageConverter.setSupportedMediaTypes(defaultFastjsonConfig.getSupportedMediaType());
return withSignMessageConverter;
}
}
package com.stylefeng.guns.rest.config;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MybatisPlus配置
*
* @author stylefeng
* @Date 2017年8月23日12:51:41
*/
@Configuration
@MapperScan(basePackages = {"com.stylefeng.guns.rest.*.dao", "com.stylefeng.guns.rest.common.persistence.dao"})
public class MybatisPlusConfig {
/**
* mybatis-plus分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
package com.stylefeng.guns.rest.config;
import com.stylefeng.guns.rest.config.properties.RestProperties;
import com.stylefeng.guns.rest.modular.auth.filter.AuthFilter;
import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
import com.stylefeng.guns.rest.modular.auth.security.impl.Base64SecurityAction;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* web配置
*
* @author fengshuonan
* @date 2017-08-23 15:48
*/
@Configuration
public class WebConfig {
@Bean
@ConditionalOnProperty(prefix = RestProperties.REST_PREFIX, name = "auth-open", havingValue = "true", matchIfMissing = true)
public AuthFilter jwtAuthenticationTokenFilter() {
return new AuthFilter();
}
@Bean
public DataSecurityAction dataSecurityAction() {
return new Base64SecurityAction();
}
}
package com.stylefeng.guns.rest.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* jwt相关配置
*
* @author fengshuonan
* @date 2017-08-23 9:23
*/
@Configuration
@ConfigurationProperties(prefix = JwtProperties.JWT_PREFIX)
public class JwtProperties {
public static final String JWT_PREFIX = "jwt";
private String header = "Authorization";
private String secret = "defaultSecret";
private Long expiration = 604800L;
private String authPath = "auth";
private String md5Key = "randomKey";
public static String getJwtPrefix() {
return JWT_PREFIX;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Long getExpiration() {
return expiration;
}
public void setExpiration(Long expiration) {
this.expiration = expiration;
}
public String getAuthPath() {
return authPath;
}
public void setAuthPath(String authPath) {
this.authPath = authPath;
}
public String getMd5Key() {
return md5Key;
}
public void setMd5Key(String md5Key) {
this.md5Key = md5Key;
}
}
package com.stylefeng.guns.rest.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 项目相关配置
*
* @author fengshuonan
* @date 2017年10月23日16:44:15
*/
@Configuration
@ConfigurationProperties(prefix = RestProperties.REST_PREFIX)
public class RestProperties {
public static final String REST_PREFIX = "rest";
private boolean authOpen = true;
private boolean signOpen = true;
public boolean isAuthOpen() {
return authOpen;
}
public void setAuthOpen(boolean authOpen) {
this.authOpen = authOpen;
}
public boolean isSignOpen() {
return signOpen;
}
public void setSignOpen(boolean signOpen) {
this.signOpen = signOpen;
}
}
package com.stylefeng.guns.rest.modular.auth.controller;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
import com.stylefeng.guns.rest.modular.auth.controller.dto.AuthRequest;
import com.stylefeng.guns.rest.modular.auth.controller.dto.AuthResponse;
import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 请求验证的
*
* @author fengshuonan
* @Date 2017/8/24 14:22
*/
@RestController
public class AuthController {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Resource(name = "simpleValidator")
private IReqValidator reqValidator;
@RequestMapping(value = "${jwt.auth-path}")
public ResponseEntity<?> createAuthenticationToken(AuthRequest authRequest) {
boolean validate = reqValidator.validate(authRequest);
if (validate) {
final String randomKey = jwtTokenUtil.getRandomKey();
final String token = jwtTokenUtil.generateToken(authRequest.getUserName(), randomKey);
return ResponseEntity.ok(new AuthResponse(token, randomKey));
} else {
throw new GunsException(BizExceptionEnum.AUTH_REQUEST_ERROR);
}
}
}
package com.stylefeng.guns.rest.modular.auth.controller.dto;
import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
/**
* 认证的请求dto
*
* @author fengshuonan
* @Date 2017/8/24 14:00
*/
public class AuthRequest implements Credence {
private String userName;
private String password;
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
@Override
public String getCredenceName() {
return this.userName;
}
@Override
public String getCredenceCode() {
return this.password;
}
}
package com.stylefeng.guns.rest.modular.auth.controller.dto;
import java.io.Serializable;
/**
* 认证的响应结果
*
* @author fengshuonan
* @Date 2017/8/24 13:58
*/
public class AuthResponse implements Serializable {
private static final long serialVersionUID = 1250166508152483573L;
/**
* jwt token
*/
private final String token;
/**
* 用于客户端混淆md5加密
*/
private final String randomKey;
public AuthResponse(String token, String randomKey) {
this.token = token;
this.randomKey = randomKey;
}
public String getToken() {
return this.token;
}
public String getRandomKey() {
return randomKey;
}
}
package com.stylefeng.guns.rest.modular.auth.converter;
/**
* 基础的传输bean
*
* @author fengshuonan
* @date 2017-08-25 15:52
*/
public class BaseTransferEntity {
private String object; //base64编码的json字符串
private String sign; //签名
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}
package com.stylefeng.guns.rest.modular.auth.converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.MD5Util;
import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
import com.stylefeng.guns.rest.config.properties.JwtProperties;
import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
/**
* 带签名的http信息转化器
*
* @author fengshuonan
* @date 2017-08-25 15:42
*/
public class WithSignMessageConverter extends FastJsonHttpMessageConverter {
@Autowired
JwtProperties jwtProperties;
@Autowired
JwtTokenUtil jwtTokenUtil;
@Autowired
DataSecurityAction dataSecurityAction;
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
InputStream in = inputMessage.getBody();
Object o = JSON.parseObject(in, super.getFastJsonConfig().getCharset(), BaseTransferEntity.class, super.getFastJsonConfig().getFeatures());
//先转化成原始的对象
BaseTransferEntity baseTransferEntity = (BaseTransferEntity) o;
//校验签名
String token = HttpKit.getRequest().getHeader(jwtProperties.getHeader()).substring(7);
String md5KeyFromToken = jwtTokenUtil.getMd5KeyFromToken(token);
String object = baseTransferEntity.getObject();
String json = dataSecurityAction.unlock(object);
String encrypt = MD5Util.encrypt(object + md5KeyFromToken);
if (encrypt.equals(baseTransferEntity.getSign())) {
System.out.println("签名校验成功!");
} else {
System.out.println("签名校验失败,数据被改动过!");
throw new GunsException(BizExceptionEnum.SIGN_ERROR);
}
//校验签名后再转化成应该的对象
return JSON.parseObject(json, type);
}
}
package com.stylefeng.guns.rest.modular.auth.filter;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.util.RenderUtil;
import com.stylefeng.guns.rest.common.exception.BizExceptionEnum;
import com.stylefeng.guns.rest.config.properties.JwtProperties;
import com.stylefeng.guns.rest.modular.auth.util.JwtTokenUtil;
import io.jsonwebtoken.JwtException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 对客户端请求的jwt token验证过滤器
*
* @author fengshuonan
* @Date 2017/8/24 14:04
*/
public class AuthFilter extends OncePerRequestFilter {
private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private JwtProperties jwtProperties;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request.getServletPath().equals("/" + jwtProperties.getAuthPath())) {
chain.doFilter(request, response);
return;
}
final String requestHeader = request.getHeader(jwtProperties.getHeader());
String authToken = null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
//验证token是否过期,包含了验证jwt是否正确
try {
boolean flag = jwtTokenUtil.isTokenExpired(authToken);
if (flag) {
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
return;
}
} catch (JwtException e) {
//有异常就是token解析失败
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
return;
}
} else {
//header没有带Bearer字段
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
return;
}
chain.doFilter(request, response);
}
}
\ No newline at end of file
package com.stylefeng.guns.rest.modular.auth.security;
/**
* <pre>
* 信息传递的保护措施(传递的数据为json)
*
* 说明:
* 可以根据实际开发时的需要,编写自己的数据加密方案,只需实现此类,并在WebConfig下配置您所编写的实现类即可
* </pre>
*
* @author fengshuonan
* @date 2017-09-18 20:41
*/
public interface DataSecurityAction {
/**
* 执行数据的保护措施
*
* @author stylefeng
* @Date 2017/9/18 20:42
*/
String doAction(String beProtected);
/**
* 解除保护
*
* @author stylefeng
* @Date 2017/9/18 20:45
*/
String unlock(String securityCode);
}
package com.stylefeng.guns.rest.modular.auth.security.impl;
import com.stylefeng.guns.rest.modular.auth.security.DataSecurityAction;
import org.springframework.util.Base64Utils;
/**
* 对数据进行base64编码的方式
*
* @author fengshuonan
* @date 2017-09-18 20:43
*/
public class Base64SecurityAction implements DataSecurityAction {
@Override
public String doAction(String beProtected) {
return Base64Utils.encodeToString(beProtected.getBytes());
}
@Override
public String unlock(String securityCode) {
byte[] bytes = Base64Utils.decodeFromString(securityCode);
return new String(bytes);
}
}
package com.stylefeng.guns.rest.modular.auth.util;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.rest.config.properties.JwtProperties;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* <p>jwt token工具类</p>
* <pre>
* jwt的claim里一般包含以下几种数据:
* 1. iss -- token的发行者
* 2. sub -- 该JWT所面向的用户
* 3. aud -- 接收该JWT的一方
* 4. exp -- token的失效时间
* 5. nbf -- 在此时间段之前,不会被处理
* 6. iat -- jwt发布时间
* 7. jti -- jwt唯一标识,防止重复使用
* </pre>
*
* @author fengshuonan
* @Date 2017/8/25 10:59
*/
@Component
public class JwtTokenUtil {
@Autowired
private JwtProperties jwtProperties;
/**
* 获取用户名从token中
*/
public String getUsernameFromToken(String token) {
return getClaimFromToken(token).getSubject();
}
/**
* 获取jwt发布时间
*/
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token).getIssuedAt();
}
/**
* 获取jwt失效时间
*/
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token).getExpiration();
}
/**
* 获取jwt接收者
*/
public String getAudienceFromToken(String token) {
return getClaimFromToken(token).getAudience();
}
/**
* 获取私有的jwt claim
*/
public String getPrivateClaimFromToken(String token, String key) {
return getClaimFromToken(token).get(key).toString();
}
/**
* 获取md5 key从token中
*/
public String getMd5KeyFromToken(String token) {
return getPrivateClaimFromToken(token, jwtProperties.getMd5Key());
}
/**
* 获取jwt的payload部分
*/
public Claims getClaimFromToken(String token) {
return Jwts.parser()
.setSigningKey(jwtProperties.getSecret())
.parseClaimsJws(token)
.getBody();
}
/**
* 解析token是否正确,不正确会报异常<br>
*/
public void parseToken(String token) throws JwtException {
Jwts.parser().setSigningKey(jwtProperties.getSecret()).parseClaimsJws(token).getBody();
}
/**
* <pre>
* 验证token是否失效
* true:过期 false:没过期
* </pre>
*/
public Boolean isTokenExpired(String token) {
try {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
} catch (ExpiredJwtException expiredJwtException) {
return true;
}
}
/**
* 生成token(通过用户名和签名时候用的随机数)
*/
public String generateToken(String userName, String randomKey) {
Map<String, Object> claims = new HashMap<>();
claims.put(jwtProperties.getMd5Key(), randomKey);
return doGenerateToken(claims, userName);
}
/**
* 生成token
*/
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = new Date();
final Date expirationDate = new Date(createdDate.getTime() + jwtProperties.getExpiration() * 1000);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
.compact();
}
/**
* 获取混淆MD5签名用的随机字符串
*/
public String getRandomKey() {
return ToolUtil.getRandomString(6);
}
}
\ No newline at end of file
package com.stylefeng.guns.rest.modular.auth.validator;
import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
/**
* <p>验证请求/auth接口时,请求参数的正确性</p>
* <p>
* <p>如果想拓展验证方法只需实现这个接口,然后在AuthenticationRestController类中注意相应实现的本接口的类即可</p>
*
* @author fengshuonan
* @date 2017-08-23 11:48
*/
public interface IReqValidator {
/**
* 通过请求参数验证
*
* @author fengshuonan
* @Date 2017/8/23 11:49
*/
boolean validate(Credence credence);
}
package com.stylefeng.guns.rest.modular.auth.validator.dto;
/**
* 验证的凭据
*
* @author fengshuonan
* @date 2017-08-27 13:27
*/
public interface Credence {
/**
* 凭据名称
*/
String getCredenceName();
/**
* 密码或者是其他的验证码之类的
*/
String getCredenceCode();
}
package com.stylefeng.guns.rest.modular.auth.validator.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.rest.common.persistence.dao.UserMapper;
import com.stylefeng.guns.rest.common.persistence.model.User;
import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 账号密码验证
*
* @author fengshuonan
* @date 2017-08-23 12:34
*/
@Service
public class DbValidator implements IReqValidator {
@Autowired
UserMapper userMapper;
@Override
public boolean validate(Credence credence) {
List<User> users = userMapper.selectList(new EntityWrapper<User>().eq("userName", credence.getCredenceName()));
if (users != null && users.size() > 0) {
return true;
} else {
return false;
}
}
}
package com.stylefeng.guns.rest.modular.auth.validator.impl;
import com.stylefeng.guns.rest.modular.auth.validator.IReqValidator;
import com.stylefeng.guns.rest.modular.auth.validator.dto.Credence;
import org.springframework.stereotype.Service;
/**
* 直接验证账号密码是不是admin
*
* @author fengshuonan
* @date 2017-08-23 12:34
*/
@Service
public class SimpleValidator implements IReqValidator {
private static String USER_NAME = "admin";
private static String PASSWORD = "admin";
@Override
public boolean validate(Credence credence) {
String userName = credence.getCredenceName();
String password = credence.getCredenceCode();
if (USER_NAME.equals(userName) && PASSWORD.equals(password)) {
return true;
} else {
return false;
}
}
}
package com.stylefeng.guns.rest.modular.example;
import com.stylefeng.guns.rest.common.SimpleObject;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 常规控制器
*
* @author fengshuonan
* @date 2017-08-23 16:02
*/
@Controller
@RequestMapping("/hello")
public class ExampleController {
@RequestMapping("")
public ResponseEntity hello(@RequestBody SimpleObject simpleObject) {
System.out.println(simpleObject.getUser());
return ResponseEntity.ok("请求成功!");
}
}
rest:
auth-open: true #jwt鉴权机制是否开启(true或者false)
sign-open: true #签名机制是否开启(true或false)
jwt:
header: Authorization #http请求头所需要的字段
secret: mySecret #jwt秘钥
expiration: 604800 #7天 单位:秒
auth-path: auth #认证请求的路径
md5-key: randomKey #md5加密混淆key
server:
port: 8080 #项目端口
mybatis-plus:
mapper-locations: classpath*:com/stylefeng/guns/rest/**/mapping/*.xml
typeAliasesPackage: com.stylefeng.guns.rest.common.persistence.model
global-config:
id-type: 0 #0:数据库ID自增 1:用户输入id 2:全局唯一id(IdWorker) 3:全局唯一ID(uuid)
db-column-underline: false
refresh-mapper: true
configuration:
map-underscore-to-camel-case: false
cache-enabled: true #配置的缓存的全局开关
lazyLoadingEnabled: true #延时加载的开关
multipleResultSetsEnabled: true #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/guns_rest?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=UTC
username: root
password: root
filters: log4j,wall,mergeStat
logging:
level.root: info
level.com.stylefeng: debug
path: logs/
file: guns-rest.log
\ No newline at end of file
package com.stylefeng.guns;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class GunsRestApplicationTests {
@Test
public void contextLoads() {
}
}
package com.stylefeng.guns.fastjson;
import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.core.util.MD5Util;
import com.stylefeng.guns.rest.common.SimpleObject;
import com.stylefeng.guns.rest.modular.auth.converter.BaseTransferEntity;
/**
* json测试
*
* @author fengshuonan
* @date 2017-08-25 16:11
*/
public class JsonTest {
public static void main(String[] args) {
String randomKey = "1xm7hw";
BaseTransferEntity baseTransferEntity = new BaseTransferEntity();
SimpleObject simpleObject = new SimpleObject();
simpleObject.setUser("fsn");
baseTransferEntity.setObject("123123");
String json = JSON.toJSONString(simpleObject);
//md5签名
String encrypt = MD5Util.encrypt(json + randomKey);
baseTransferEntity.setSign(encrypt);
System.out.println(JSON.toJSONString(baseTransferEntity));
}
}
package com.stylefeng.guns.generator;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* 实体生成
*
* @author fengshuonan
* @date 2017-08-23 12:15
*/
public class EntityGenerator {
@Test
public void entityGenerator() {
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("D:\\tmp\\guns\\guns-rest\\src\\main\\java");//这里写你自己的java目录
gc.setFileOverride(true);//是否覆盖
gc.setActiveRecord(true);
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
gc.setAuthor("stylefeng");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert() {
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
return super.processTypeConvert(fieldType);
}
});
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/rest?characterEncoding=utf8");
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//strategy.setTablePrefix(new String[]{"_"});// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[]{"user"});
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent(null);
pc.setEntity("com.stylefeng.guns.rest.persistence.model");
pc.setMapper("com.stylefeng.guns.rest.persistence.dao");
pc.setXml("com.stylefeng.guns.rest.persistence.dao.mapping");
pc.setService("TTT"); //本项目没用,生成之后删掉
pc.setServiceImpl("TTT"); //本项目没用,生成之后删掉
pc.setController("TTT"); //本项目没用,生成之后删掉
mpg.setPackageInfo(pc);
// 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
this.setMap(map);
}
};
mpg.setCfg(cfg);
// 执行生成
mpg.execute();
// 打印注入设置
System.err.println(mpg.getCfg().getMap().get("abc"));
}
}
package com.stylefeng.guns.jwt;
import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.core.util.MD5Util;
import com.stylefeng.guns.rest.common.SimpleObject;
import com.stylefeng.guns.rest.modular.auth.converter.BaseTransferEntity;
import com.stylefeng.guns.rest.modular.auth.security.impl.Base64SecurityAction;
/**
* jwt测试
*
* @author fengshuonan
* @date 2017-08-21 16:34
*/
public class DecryptTest {
public static void main(String[] args) {
String salt = "0iqwhi";
SimpleObject simpleObject = new SimpleObject();
simpleObject.setUser("stylefeng");
simpleObject.setAge(12);
simpleObject.setName("ffff");
simpleObject.setTips("code");
String jsonString = JSON.toJSONString(simpleObject);
String encode = new Base64SecurityAction().doAction(jsonString);
String md5 = MD5Util.encrypt(encode + salt);
BaseTransferEntity baseTransferEntity = new BaseTransferEntity();
baseTransferEntity.setObject(encode);
baseTransferEntity.setSign(md5);
System.out.println(JSON.toJSONString(baseTransferEntity));
}
}
package com.stylefeng.guns.jwt;
import com.stylefeng.guns.core.util.IdGenerator;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.DefaultClaims;
import io.jsonwebtoken.impl.crypto.MacProvider;
import java.security.Key;
/**
* jwt测试
*
* @author fengshuonan
* @date 2017-08-21 16:34
*/
public class JWTTest {
public static void main(String[] args) {
Key key = MacProvider.generateKey();
String compactJws = Jwts.builder()
.setSubject("Joe")
.setClaims(new DefaultClaims().setId(IdGenerator.getId()))
.signWith(SignatureAlgorithm.HS512, key)
.compact();
System.out.println(compactJws);
assert Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws).getBody().getSubject().equals("Joe");
try {
Claims body = Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws).getBody();
System.out.println(body);
System.out.println(body.getExpiration());
System.out.println("trust");
} catch (SignatureException e) {
System.out.println("not trust");
} catch (ExpiredJwtException e) {
System.out.println("ExpiredJwtException");
}
}
}
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
<modules> <modules>
<module>guns-admin</module> <module>guns-admin</module>
<module>guns-core</module> <module>guns-core</module>
<module>guns-rest</module>
<module>guns-generator</module> <module>guns-generator</module>
</modules> </modules>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment