用户添加apikey

This commit is contained in:
Captain.B 2020-06-22 18:22:58 +08:00
parent f8cb40cb10
commit 78b0f4a4d9
22 changed files with 1355 additions and 1 deletions

View File

@ -0,0 +1,22 @@
package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserKey implements Serializable {
private String id;
private String userId;
private String accessKey;
private String secretKey;
private Long createTime;
private String status;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,610 @@
package io.metersphere.base.domain;
import java.util.ArrayList;
import java.util.List;
public class UserKeyExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public UserKeyExample() {
oredCriteria = new ArrayList<Criteria>();
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andUserIdIsNull() {
addCriterion("user_id is null");
return (Criteria) this;
}
public Criteria andUserIdIsNotNull() {
addCriterion("user_id is not null");
return (Criteria) this;
}
public Criteria andUserIdEqualTo(String value) {
addCriterion("user_id =", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdNotEqualTo(String value) {
addCriterion("user_id <>", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdGreaterThan(String value) {
addCriterion("user_id >", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdGreaterThanOrEqualTo(String value) {
addCriterion("user_id >=", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdLessThan(String value) {
addCriterion("user_id <", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdLessThanOrEqualTo(String value) {
addCriterion("user_id <=", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdLike(String value) {
addCriterion("user_id like", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdNotLike(String value) {
addCriterion("user_id not like", value, "userId");
return (Criteria) this;
}
public Criteria andUserIdIn(List<String> values) {
addCriterion("user_id in", values, "userId");
return (Criteria) this;
}
public Criteria andUserIdNotIn(List<String> values) {
addCriterion("user_id not in", values, "userId");
return (Criteria) this;
}
public Criteria andUserIdBetween(String value1, String value2) {
addCriterion("user_id between", value1, value2, "userId");
return (Criteria) this;
}
public Criteria andUserIdNotBetween(String value1, String value2) {
addCriterion("user_id not between", value1, value2, "userId");
return (Criteria) this;
}
public Criteria andAccessKeyIsNull() {
addCriterion("access_key is null");
return (Criteria) this;
}
public Criteria andAccessKeyIsNotNull() {
addCriterion("access_key is not null");
return (Criteria) this;
}
public Criteria andAccessKeyEqualTo(String value) {
addCriterion("access_key =", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyNotEqualTo(String value) {
addCriterion("access_key <>", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyGreaterThan(String value) {
addCriterion("access_key >", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyGreaterThanOrEqualTo(String value) {
addCriterion("access_key >=", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyLessThan(String value) {
addCriterion("access_key <", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyLessThanOrEqualTo(String value) {
addCriterion("access_key <=", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyLike(String value) {
addCriterion("access_key like", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyNotLike(String value) {
addCriterion("access_key not like", value, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyIn(List<String> values) {
addCriterion("access_key in", values, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyNotIn(List<String> values) {
addCriterion("access_key not in", values, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyBetween(String value1, String value2) {
addCriterion("access_key between", value1, value2, "accessKey");
return (Criteria) this;
}
public Criteria andAccessKeyNotBetween(String value1, String value2) {
addCriterion("access_key not between", value1, value2, "accessKey");
return (Criteria) this;
}
public Criteria andSecretKeyIsNull() {
addCriterion("secret_key is null");
return (Criteria) this;
}
public Criteria andSecretKeyIsNotNull() {
addCriterion("secret_key is not null");
return (Criteria) this;
}
public Criteria andSecretKeyEqualTo(String value) {
addCriterion("secret_key =", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyNotEqualTo(String value) {
addCriterion("secret_key <>", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyGreaterThan(String value) {
addCriterion("secret_key >", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyGreaterThanOrEqualTo(String value) {
addCriterion("secret_key >=", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyLessThan(String value) {
addCriterion("secret_key <", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyLessThanOrEqualTo(String value) {
addCriterion("secret_key <=", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyLike(String value) {
addCriterion("secret_key like", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyNotLike(String value) {
addCriterion("secret_key not like", value, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyIn(List<String> values) {
addCriterion("secret_key in", values, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyNotIn(List<String> values) {
addCriterion("secret_key not in", values, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyBetween(String value1, String value2) {
addCriterion("secret_key between", value1, value2, "secretKey");
return (Criteria) this;
}
public Criteria andSecretKeyNotBetween(String value1, String value2) {
addCriterion("secret_key not between", value1, value2, "secretKey");
return (Criteria) this;
}
public Criteria andCreateTimeIsNull() {
addCriterion("create_time is null");
return (Criteria) this;
}
public Criteria andCreateTimeIsNotNull() {
addCriterion("create_time is not null");
return (Criteria) this;
}
public Criteria andCreateTimeEqualTo(Long value) {
addCriterion("create_time =", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotEqualTo(Long value) {
addCriterion("create_time <>", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThan(Long value) {
addCriterion("create_time >", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("create_time >=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThan(Long value) {
addCriterion("create_time <", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThanOrEqualTo(Long value) {
addCriterion("create_time <=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeIn(List<Long> values) {
addCriterion("create_time in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotIn(List<Long> values) {
addCriterion("create_time not in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeBetween(Long value1, Long value2) {
addCriterion("create_time between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotBetween(Long value1, Long value2) {
addCriterion("create_time not between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andStatusIsNull() {
addCriterion("status is null");
return (Criteria) this;
}
public Criteria andStatusIsNotNull() {
addCriterion("status is not null");
return (Criteria) this;
}
public Criteria andStatusEqualTo(String value) {
addCriterion("status =", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotEqualTo(String value) {
addCriterion("status <>", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThan(String value) {
addCriterion("status >", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThanOrEqualTo(String value) {
addCriterion("status >=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThan(String value) {
addCriterion("status <", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThanOrEqualTo(String value) {
addCriterion("status <=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLike(String value) {
addCriterion("status like", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotLike(String value) {
addCriterion("status not like", value, "status");
return (Criteria) this;
}
public Criteria andStatusIn(List<String> values) {
addCriterion("status in", values, "status");
return (Criteria) this;
}
public Criteria andStatusNotIn(List<String> values) {
addCriterion("status not in", values, "status");
return (Criteria) this;
}
public Criteria andStatusBetween(String value1, String value2) {
addCriterion("status between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andStatusNotBetween(String value1, String value2) {
addCriterion("status not between", value1, value2, "status");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}

View File

@ -0,0 +1,31 @@
package io.metersphere.base.mapper;
import io.metersphere.base.domain.UserKey;
import io.metersphere.base.domain.UserKeyExample;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserKeyMapper {
long countByExample(UserKeyExample example);
int deleteByExample(UserKeyExample example);
int deleteByPrimaryKey(String id);
int insert(UserKey record);
int insertSelective(UserKey record);
List<UserKey> selectByExample(UserKeyExample example);
UserKey selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") UserKey record, @Param("example") UserKeyExample example);
int updateByExample(@Param("record") UserKey record, @Param("example") UserKeyExample example);
int updateByPrimaryKeySelective(UserKey record);
int updateByPrimaryKey(UserKey record);
}

View File

@ -0,0 +1,228 @@
<?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="io.metersphere.base.mapper.UserKeyMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.UserKey">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="user_id" jdbcType="VARCHAR" property="userId" />
<result column="access_key" jdbcType="VARCHAR" property="accessKey" />
<result column="secret_key" jdbcType="VARCHAR" property="secretKey" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="status" jdbcType="VARCHAR" property="status" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
AND ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
</when>
<when test="criterion.listValue">
AND ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
AND ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
</when>
<when test="criterion.listValue">
AND ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, user_id, access_key, secret_key, create_time, status
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.UserKeyExample" resultMap="BaseResultMap">
SELECT
<if test="distinct">
DISTINCT
</if>
<include refid="Base_Column_List" />
FROM user_key
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
ORDER BY ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM user_key
WHERE id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
DELETE FROM user_key
WHERE id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.UserKeyExample">
DELETE FROM user_key
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.UserKey">
INSERT INTO user_key (id, user_id, access_key,
secret_key, create_time, status
)
VALUES (#{id,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{accessKey,jdbcType=VARCHAR},
#{secretKey,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.UserKey">
INSERT INTO user_key
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="userId != null">
user_id,
</if>
<if test="accessKey != null">
access_key,
</if>
<if test="secretKey != null">
secret_key,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="status != null">
status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="userId != null">
#{userId,jdbcType=VARCHAR},
</if>
<if test="accessKey != null">
#{accessKey,jdbcType=VARCHAR},
</if>
<if test="secretKey != null">
#{secretKey,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.UserKeyExample" resultType="java.lang.Long">
SELECT count(*) FROM user_key
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
UPDATE user_key
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.userId != null">
user_id = #{record.userId,jdbcType=VARCHAR},
</if>
<if test="record.accessKey != null">
access_key = #{record.accessKey,jdbcType=VARCHAR},
</if>
<if test="record.secretKey != null">
secret_key = #{record.secretKey,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
UPDATE user_key
SET id = #{record.id,jdbcType=VARCHAR},
user_id = #{record.userId,jdbcType=VARCHAR},
access_key = #{record.accessKey,jdbcType=VARCHAR},
secret_key = #{record.secretKey,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
status = #{record.status,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.UserKey">
UPDATE user_key
<set>
<if test="userId != null">
user_id = #{userId,jdbcType=VARCHAR},
</if>
<if test="accessKey != null">
access_key = #{accessKey,jdbcType=VARCHAR},
</if>
<if test="secretKey != null">
secret_key = #{secretKey,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
</if>
<if test="status != null">
status = #{status,jdbcType=VARCHAR},
</if>
</set>
WHERE id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.UserKey">
UPDATE user_key
SET user_id = #{userId,jdbcType=VARCHAR},
access_key = #{accessKey,jdbcType=VARCHAR},
secret_key = #{secretKey,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
status = #{status,jdbcType=VARCHAR}
WHERE id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -0,0 +1,5 @@
package io.metersphere.commons.constants;
public enum ApiKeyConstants {
ACTIVE, DISABLED
}

View File

@ -1,5 +1,6 @@
package io.metersphere.config;
import io.metersphere.security.ApiKeyFilter;
import io.metersphere.security.LoginFilter;
import io.metersphere.security.ShiroDBRealm;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
@ -37,6 +38,7 @@ public class ShiroConfig {
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setSuccessUrl("/");
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
filterChainDefinitionMap.put("/resource/**", "anon");
@ -51,7 +53,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/403", "anon");
filterChainDefinitionMap.put("/anonymous/**", "anon");
filterChainDefinitionMap.put("/**", "authc");
filterChainDefinitionMap.put("/**", "apikey, authc");
return shiroFilterFactoryBean;
}

View File

@ -0,0 +1,47 @@
package io.metersphere.controller;
import io.metersphere.base.domain.UserKey;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.service.UserKeyService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("user/key")
public class UserKeysController {
@Resource
private UserKeyService userKeyService;
@GetMapping("info")
public List<UserKey> getUserKeysInfo() {
String userId = SessionUtils.getUser().getId();
return userKeyService.getUserKeysInfo(userId);
}
@GetMapping("generate")
public void generateUserKey() {
String userId = SessionUtils.getUser().getId();
userKeyService.generateUserKey(userId);
}
@GetMapping("delete/{id}")
public void deleteUserKey(@PathVariable String id) {
userKeyService.deleteUserKey(id);
}
@GetMapping("active/{id}")
public void activeUserKey(@PathVariable String id) {
userKeyService.activeUserKey(id);
}
@GetMapping("disable/{id}")
public void disabledUserKey(@PathVariable String id) {
userKeyService.disableUserKey(id);
}
}

View File

@ -0,0 +1,46 @@
package io.metersphere.security;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class ApiKeyFilter extends AnonymousFilter {
@Override
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
try {
if (!SecurityUtils.getSubject().isAuthenticated()) {
String userId = ApiKeyHandler.getUser(WebUtils.toHttp(request));
if (StringUtils.isNotBlank(userId)) {
if (LogUtil.getLogger().isDebugEnabled()) {
LogUtil.getLogger().debug("user auth: " + userId);
}
SecurityUtils.getSubject().login(new UsernamePasswordToken(userId, ApiKeySessionHandler.random));
}
} else {
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
String userId = ApiKeyHandler.getUser(WebUtils.toHttp(request));
SecurityUtils.getSubject().login(new UsernamePasswordToken(userId, ApiKeySessionHandler.random));
}
}
if (!SecurityUtils.getSubject().isAuthenticated()) {
((HttpServletResponse) response).setHeader("Authentication-Status", "invalid");
}
} catch (Exception e) {
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
throw e;
}
LogUtil.getLogger().error("failed to handle single sign on..", e);
}
return true;
}
}

View File

@ -0,0 +1,64 @@
package io.metersphere.security;
import io.metersphere.base.domain.UserKey;
import io.metersphere.commons.utils.CodingUtil;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.service.UserKeyService;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
public class ApiKeyHandler {
public static final String API_ACCESS_KEY = "accessKey";
public static final String API_SIGNATURE = "signature";
public static String getUser(HttpServletRequest request) {
if (request == null) {
return null;
}
return getUser(request.getHeader(API_ACCESS_KEY), request.getHeader(API_SIGNATURE));
}
public static Boolean isApiKeyCall(HttpServletRequest request) {
if (request == null) {
return false;
}
return !StringUtils.isBlank(request.getHeader(API_ACCESS_KEY)) && !StringUtils.isBlank(request.getHeader(API_SIGNATURE));
}
public static String getUser(String accessKey, String signature) {
if (StringUtils.isBlank(accessKey) || StringUtils.isBlank(signature)) {
return null;
}
UserKey userKey = CommonBeanFactory.getBean(UserKeyService.class).getUserKey(accessKey);
if (userKey == null) {
throw new RuntimeException("invalid accessKey");
}
String signatureDecrypt;
try {
signatureDecrypt = CodingUtil.aesDecrypt(signature, userKey.getSecretKey(), accessKey);
} catch (Throwable t) {
throw new RuntimeException("invalid signature");
}
String[] signatureArray = StringUtils.split(StringUtils.trimToNull(signatureDecrypt), "|");
if (signatureArray.length < 2) {
throw new RuntimeException("invalid signature");
}
if (!StringUtils.equals(accessKey, signatureArray[0])) {
throw new RuntimeException("invalid signature");
}
long signatureTime;
try {
signatureTime = Long.parseLong(signatureArray[signatureArray.length - 1]);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (Math.abs(System.currentTimeMillis() - signatureTime) > 1800000) {
//签名30分钟超时
throw new RuntimeException("expired signature");
}
return userKey.getUserId();
}
}

View File

@ -0,0 +1,59 @@
package io.metersphere.security;
import io.metersphere.commons.utils.EncryptUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
public class ApiKeySessionHandler {
private static Logger logger = LoggerFactory.getLogger(ApiKeySessionHandler.class);
public static String random = UUID.randomUUID().toString() + UUID.randomUUID().toString();
public static String generateId(String authInfo) {
return SessionGenerator.generateId(authInfo);
}
public static String validate(HttpServletRequest request) {
try {
String v = request.getHeader(ApiKeyHandler.API_SIGNATURE);
if (StringUtils.isNotBlank(v)) {
return SessionGenerator.fromId(v);
}
} catch (Exception e) {
logger.error("failed to validate", e);
}
return null;
}
public static class SessionGenerator {
public SessionGenerator() {
}
public static String generateId(String authInfo) {
return EncryptUtils.aesEncrypt(parse2Str(authInfo)).toString();
}
public static String fromId(String sessionId) {
String authInfoString = EncryptUtils.aesDecrypt(sessionId).toString();
return fromStr(authInfoString);
}
private static String parse2Str(String authInfo) {
return UUID.randomUUID().toString() + "|" + authInfo + "|" + System.currentTimeMillis();
}
private static String fromStr(String authInfoString) {
String[] sp = authInfoString.split("\\|");
return sp[1];
}
}
}

View File

@ -83,6 +83,12 @@ public class ShiroDBRealm extends AuthorizingRealm {
SessionUtils.putUser(sessionUser);
return new SimpleAuthenticationInfo(userId, password, getName());
}
// apikey 校验不验证密码
if (ApiKeySessionHandler.random.equalsIgnoreCase(password)) {
SessionUser sessionUser = SessionUser.fromUser(user);
SessionUtils.putUser(sessionUser);
return new SimpleAuthenticationInfo(userId, password, getName());
}
// 密码验证
if (!userService.checkUserPassword(userId, password)) {
throw new IncorrectCredentialsException(Translator.get("password_is_incorrect"));

View File

@ -0,0 +1,83 @@
package io.metersphere.service;
import io.metersphere.base.domain.UserKey;
import io.metersphere.base.domain.UserKeyExample;
import io.metersphere.base.mapper.UserKeyMapper;
import io.metersphere.commons.constants.ApiKeyConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.i18n.Translator;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
@Service
public class UserKeyService {
@Resource
private UserKeyMapper userKeyMapper;
@Resource
private UserService userService;
public List<UserKey> getUserKeysInfo(String userId) {
UserKeyExample userKeysExample = new UserKeyExample();
userKeysExample.createCriteria().andUserIdEqualTo(userId);
userKeysExample.setOrderByClause("create_time");
return userKeyMapper.selectByExample(userKeysExample);
}
public UserKey generateUserKey(String userId) {
if (userService.getUserDTO(userId) == null) {
MSException.throwException(Translator.get("user_not_exist") + userId);
}
UserKeyExample userKeysExample = new UserKeyExample();
userKeysExample.createCriteria().andUserIdEqualTo(userId);
List<UserKey> userKeysList = userKeyMapper.selectByExample(userKeysExample);
if (!CollectionUtils.isEmpty(userKeysList) && userKeysList.size() >= 5) {
MSException.throwException(Translator.get("user_apikey_limit"));
}
UserKey userKeys = new UserKey();
userKeys.setId(UUID.randomUUID().toString());
userKeys.setUserId(userId);
userKeys.setStatus(ApiKeyConstants.ACTIVE.name());
userKeys.setAccessKey(RandomStringUtils.randomAlphanumeric(16));
userKeys.setSecretKey(RandomStringUtils.randomAlphanumeric(16));
userKeys.setCreateTime(System.currentTimeMillis());
userKeyMapper.insert(userKeys);
return userKeyMapper.selectByPrimaryKey(userKeys.getId());
}
public void deleteUserKey(String id) {
userKeyMapper.deleteByPrimaryKey(id);
}
public void activeUserKey(String id) {
UserKey userKeys = new UserKey();
userKeys.setId(id);
userKeys.setStatus(ApiKeyConstants.ACTIVE.name());
userKeyMapper.updateByPrimaryKeySelective(userKeys);
}
public void disableUserKey(String id) {
UserKey userKeys = new UserKey();
userKeys.setId(id);
userKeys.setStatus(ApiKeyConstants.DISABLED.name());
userKeyMapper.updateByPrimaryKeySelective(userKeys);
}
public UserKey getUserKey(String accessKey) {
UserKeyExample userKeyExample = new UserKeyExample();
userKeyExample.createCriteria().andAccessKeyEqualTo(accessKey).andStatusEqualTo(ApiKeyConstants.ACTIVE.name());
List<UserKey> userKeysList = userKeyMapper.selectByExample(userKeyExample);
if (!CollectionUtils.isEmpty(userKeysList)) {
return userKeysList.get(0);
}
return null;
}
}

View File

@ -0,0 +1,14 @@
CREATE TABLE `user_key` (
`id` varchar(50) NOT NULL DEFAULT '' COMMENT 'user_key ID',
`user_id` varchar(50) NOT NULL COMMENT '用户ID',
`access_key` varchar(50) NOT NULL COMMENT 'access_key',
`secret_key` varchar(50) NOT NULL COMMENT 'secret key',
`create_time` bigint(13) NOT NULL COMMENT '创建时间',
`status` varchar(10) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`id`),
UNIQUE KEY `IDX_AK` (`access_key`),
KEY `IDX_USER_ID` (`user_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

View File

@ -27,6 +27,7 @@ user_locked=the user has been locked.
user_expires=user expires.
not_authorized=not authorized.
login_fail=Login fail
user_apikey_limit=Can have up to 5 api keys
#load test
edit_load_test_not_found=Cannot edit test, test not found=
run_load_test_not_found=Cannot run test, test not found=

View File

@ -27,6 +27,7 @@ excessive_attempts=操作频繁
user_locked=用户被锁定
user_expires=用户过期
not_authorized=未经授权
user_apikey_limit=最多能有5个Api key
#load test
edit_load_test_not_found=无法编辑测试,未找到测试:
run_load_test_not_found=无法运行测试,未找到测试:

View File

@ -27,6 +27,7 @@ user_locked=用戶被鎖定
user_expires=用戶過期
not_authorized=未經授權。
login_fail=登入失敗
user_apikey_limit=最多能有5個Api key
#load test
edit_load_test_not_found=無法編輯測試,未找到測試:
run_load_test_not_found=無法運行測試,未找到測試:

View File

@ -32,6 +32,7 @@ import TestCase from "../../track/case/TestCase";
import TestTrack from "../../track/TestTrack";
import ApiReportList from "../../api/report/ApiReportList";
import axios from "axios";
import ApiKeys from "../../settings/personal/ApiKeys";
Vue.use(VueRouter);
@ -70,6 +71,10 @@ const router = new VueRouter({
path: 'personsetting',
component: PersonSetting
},
{
path: 'apikeys',
component: ApiKeys
},
{
path: 'member',
component: Member

View File

@ -38,6 +38,7 @@
<span>{{$t('commons.personal_info')}}</span>
</template>
<el-menu-item index="/setting/personsetting">{{$t('commons.personal_setting')}}</el-menu-item>
<el-menu-item index="/setting/apikeys">API Keys</el-menu-item>
</el-submenu>
</el-menu>

View File

@ -0,0 +1,125 @@
<template>
<div v-loading="result.loading">
<el-card class="table-card">
<template v-slot:header>
<div>
<el-row class="table-title" type="flex" justify="space-between" align="middle">
<span class="title">API Keys</span>
</el-row>
<el-row type="flex" justify="space-between" align="middle">
<el-button @click="createApiKey()" plain type="el-icon-question" icon="el-icon-circle-plus-outline"
size="mini">
{{$t('commons.create')}}
</el-button>
</el-row>
</div>
</template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="accessKey" label="Access Key"/>
<el-table-column prop="secretKey" label="Secret Key"/>
<el-table-column prop="status" :label="$t('commons.status')">
<template v-slot:default="scope">
<el-switch v-model="scope.row.status"
active-color="#13ce66"
inactive-color="#ff4949"
active-value="ACTIVE"
inactive-value="DISABLED"
@change="changeSwitch(scope.row)"
/>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('commons.operating')">
<template v-slot:default="scope">
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete"
type="danger" @exec="deleteApiKey(scope.row)"/>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
import MsDialogFooter from "../../common/components/MsDialogFooter";
import {getCurrentUser} from "../../../../common/js/utils";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import MsTableHeader from "../../common/components/MsTableHeader";
export default {
name: "MsApiKeys",
components: {MsDialogFooter, MsTableOperatorButton, MsTableHeader},
data() {
return {
result: {},
updateVisible: false,
editPasswordVisible: false,
apiKeysVisible: false,
condition: {},
tableData: [],
}
},
activated() {
this.search();
},
methods: {
currentUser: () => {
return getCurrentUser();
},
search() {
this.result = this.$get("/user/key/info", response => {
this.tableData = response.data;
this.tableData.forEach(d => d.show = false);
}
)
},
deleteApiKey(row) {
this.$confirm(this.$t('user.apikey_delete_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.result = this.$get("/user/key/delete/" + row.id, response => {
this.$success(this.$t('commons.delete_success'));
this.search();
})
}).catch(() => {
this.$info(this.$t('commons.delete_cancel'));
});
},
createApiKey() {
this.result = this.$get("/user/key/generate", response => {
this.$success(this.$t('commons.save_success'));
this.search();
})
},
changeSwitch(row) {
if (row.status === 'ACTIVE') {
this.result = this.$get("/user/key/active/" + row.id, response => {
this.$success(this.$t('commons.save_success'));
});
}
if (row.status === 'DISABLED') {
this.result = this.$get("/user/key/disable/" + row.id, response => {
this.$success(this.$t('commons.save_success'));
});
}
},
}
}
</script>
<style scoped>
</style>

View File

@ -174,6 +174,7 @@ export default {
'mobile_number_format_is_incorrect': 'Mobile number format is incorrect',
'email_format_is_incorrect': 'Email format is incorrect',
'delete_confirm': 'Are you sure you want to delete this User?',
'apikey_delete_confirm': 'Are you sure you want to delete this API Key?',
'input_id_placeholder': 'Please enter ID (only supports numbers and English letters)'
},
role: {

View File

@ -173,6 +173,7 @@ export default {
'mobile_number_format_is_incorrect': '手机号码格式不正确',
'email_format_is_incorrect': '邮箱格式不正确',
'delete_confirm': '这个用户确定要删除吗?',
'apikey_delete_confirm': '这个 API Key 确定要删除吗?',
'input_id_placeholder': '请输入ID (只支持数字、英文字母)'
},
role: {

View File

@ -171,6 +171,7 @@ export default {
'mobile_number_format_is_incorrect': '手機號碼格式不正確',
'email_format_is_incorrect': '郵箱格式不正確',
'delete_confirm': '這個用戶確定要刪除嗎?',
'apikey_delete_confirm': '這個 API Key 確定要刪除嗎?',
'input_id_placeholder': '請輸入ID (只支持數字、英文字母)'
},
role: {