前端:整理首页

前端:修复订单列表和详情价格展示错误
前端:H5 页面的登陆拦截补充
后端 + 前端:增加 refreshToken 刷新 accessToken
This commit is contained in:
YunaiV
2019-04-22 19:11:23 +08:00
parent 3e156b18ee
commit f46a4f7010
28 changed files with 292 additions and 94 deletions

View File

@@ -2,12 +2,13 @@ package cn.iocoder.mall.user.application.controller.users;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.user.application.convert.PassportConvert;
import cn.iocoder.mall.user.application.vo.users.UsersAccessTokenVO;
import cn.iocoder.mall.user.sdk.annotation.PermitAll;
import cn.iocoder.mall.user.api.MobileCodeService;
import cn.iocoder.mall.user.api.OAuth2Service;
import cn.iocoder.mall.user.api.UserService;
import cn.iocoder.mall.user.api.bo.OAuth2AccessTokenBO;
import cn.iocoder.mall.user.application.vo.users.MobileRegisterVO;
import cn.iocoder.mall.user.application.vo.users.UsersMobileRegisterVO;
import com.alibaba.dubbo.config.annotation.Reference;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -44,8 +45,8 @@ public class PassportController {
@ApiImplicitParam(name = "mobile", value = "手机号", required = true, example = "15601691300"),
@ApiImplicitParam(name = "code", value = "验证码", required = true, example = "9999")
})
public CommonResult<MobileRegisterVO> mobileRegister(@RequestParam("mobile") String mobile,
@RequestParam("code") String code) {
public CommonResult<UsersMobileRegisterVO> mobileRegister(@RequestParam("mobile") String mobile,
@RequestParam("code") String code) {
CommonResult<OAuth2AccessTokenBO> result = oauth2Service.getAccessToken(mobile, code);
return PassportConvert.INSTANCE.convert(result);
}
@@ -74,7 +75,12 @@ public class PassportController {
return null;
}
// TODO 功能:刷新 token
@PermitAll
@PostMapping("/refresh_token") // TODO 功能:刷新 token
public CommonResult<UsersAccessTokenVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
CommonResult<OAuth2AccessTokenBO> result = oauth2Service.refreshToken(refreshToken);
return PassportConvert.INSTANCE.convert2(result);
}
// TODO 功能:退出,销毁 token
}
}

View File

@@ -2,7 +2,8 @@ package cn.iocoder.mall.user.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.user.api.bo.OAuth2AccessTokenBO;
import cn.iocoder.mall.user.application.vo.users.MobileRegisterVO;
import cn.iocoder.mall.user.application.vo.users.UsersAccessTokenVO;
import cn.iocoder.mall.user.application.vo.users.UsersMobileRegisterVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@@ -13,9 +14,12 @@ public interface PassportConvert {
PassportConvert INSTANCE = Mappers.getMapper(PassportConvert.class);
@Mappings({})
MobileRegisterVO convert(OAuth2AccessTokenBO oauth2AccessTokenBO);
UsersMobileRegisterVO convert(OAuth2AccessTokenBO oauth2AccessTokenBO);
@Mappings({})
CommonResult<MobileRegisterVO> convert(CommonResult<OAuth2AccessTokenBO> oauth2AccessTokenBO);
CommonResult<UsersMobileRegisterVO> convert(CommonResult<OAuth2AccessTokenBO> oauth2AccessTokenBO);
}
@Mappings({})
CommonResult<UsersAccessTokenVO> convert2(CommonResult<OAuth2AccessTokenBO> result);
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.mall.user.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel("认证令牌 VO")
@Data
@Accessors(chain = true)
public class UsersAccessTokenVO {
@ApiModelProperty(value = "访问令牌", required = true, example = "2e3d7635c15e47e997611707a237859f")
private String accessToken;
@ApiModelProperty(value = "刷新令牌", required = true, example = "d091e7c35bbb4313b0f557a6ef23d033")
private String refreshToken;
@ApiModelProperty(value = "过期时间,单位:秒", required = true, example = "2879")
private Integer expiresIn;
}

View File

@@ -8,7 +8,7 @@ import lombok.experimental.Accessors;
@ApiModel("手机注册结果 VO")
@Data
@Accessors(chain = true)
public class MobileRegisterVO {
public class UsersMobileRegisterVO {
@ApiModelProperty(value = "访问令牌", required = true, example = "2e3d7635c15e47e997611707a237859f")
private String accessToken;

View File

@@ -17,8 +17,8 @@ public interface OAuth2Service {
*/
CommonResult<OAuth2AuthenticationBO> checkToken(String accessToken);
// TODO @see 刷新 token
CommonResult<OAuth2AccessTokenBO> refreshToken(String refreshToken);
// TODO @see 移除 token
}
}

View File

@@ -12,10 +12,13 @@ public enum UserErrorCodeEnum {
OAUTH2_INVALID_GRANT_BAD_CREDENTIALS(1001001001, "密码不正确"), // 暂时没用到
OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到
OAUTH2_INVALID_GRANT(1001001010, ""), // 预留
OAUTH_INVALID_TOKEN_NOT_FOUND(1001001011, "访问令牌不存在"),
OAUTH_INVALID_TOKEN_EXPIRED(1001001012, "访问令牌已过期"),
OAUTH_INVALID_TOKEN_INVALID(1001001013, "访问令牌已失效"),
OAUTH_INVALID_TOKEN(1001001020, ""), // 预留
OAUTH_INVALID_ACCESS_TOKEN_NOT_FOUND(1001001011, "访问令牌不存在"),
OAUTH_INVALID_ACCESS_TOKEN_EXPIRED(1001001012, "访问令牌已过期"),
OAUTH_INVALID_ACCESS_TOKEN_INVALID(1001001013, "访问令牌已失效"),
OAUTH_INVALID_REFRESH_TOKEN(1001001020, ""), // 预留
OAUTH_INVALID_REFRESH_TOKEN_NOT_FOUND(1001001021, "刷新令牌不存在"),
OAUTH_INVALID_REFRESH_TOKEN_EXPIRED(1001001022, "访问令牌已过期"),
OAUTH_INVALID_REFRESH_TOKEN_INVALID(1001001023, "刷新令牌已失效"),
// ========== 用户模块 ==========
USER_MOBILE_NOT_REGISTERED(1001002000, "手机号未注册用户"),
@@ -54,4 +57,4 @@ public enum UserErrorCodeEnum {
return message;
}
}
}

View File

@@ -13,4 +13,6 @@ public interface OAuth2AccessTokenMapper {
void updateToInvalidByUserId(@Param("userId") Integer userId);
}
void updateToInvalidByRefreshToken(@Param("refreshToken") String refreshToken);
}

View File

@@ -11,4 +11,6 @@ public interface OAuth2RefreshTokenMapper {
void updateToInvalidByUserId(@Param("userId") Integer userId);
}
OAuth2RefreshTokenDO selectById(@Param("id") String id);
}

View File

@@ -82,18 +82,39 @@ public class OAuth2ServiceImpl implements OAuth2Service {
public CommonResult<OAuth2AuthenticationBO> checkToken(String accessToken) throws ServiceException {
OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByTokenId(accessToken);
if (accessTokenDO == null) { // 不存在
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_TOKEN_NOT_FOUND.getCode());
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_ACCESS_TOKEN_NOT_FOUND.getCode());
}
if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_TOKEN_EXPIRED.getCode());
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_ACCESS_TOKEN_EXPIRED.getCode());
}
if (!accessTokenDO.getValid()) { // 无效
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_TOKEN_INVALID.getCode());
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_ACCESS_TOKEN_INVALID.getCode());
}
// 转换返回
return CommonResult.success(OAuth2Convert.INSTANCE.convertToAuthentication(accessTokenDO));
}
@Override
public CommonResult<OAuth2AccessTokenBO> refreshToken(String refreshToken) {
OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectById(refreshToken);
// 校验刷新令牌是否合法
if (refreshTokenDO == null) { // 不存在
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_REFRESH_TOKEN_NOT_FOUND.getCode());
}
if (refreshTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_REFRESH_TOKEN_EXPIRED.getCode());
}
if (!refreshTokenDO.getValid()) { // 无效
return ServiceExceptionUtil.error(UserErrorCodeEnum.OAUTH_INVALID_REFRESH_TOKEN_INVALID.getCode());
}
// 标记 refreshToken 对应的 accessToken 都不合法
oauth2AccessTokenMapper.updateToInvalidByRefreshToken(refreshToken);
// 创建访问令牌
OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(refreshTokenDO.getUserId(), refreshTokenDO.getId());
// 转换返回
return CommonResult.success(OAuth2Convert.INSTANCE.convertToAccessTokenWithExpiresIn(oauth2AccessTokenDO));
}
/**
* 移除用户对应的 Token
*
@@ -134,4 +155,4 @@ public class OAuth2ServiceImpl implements OAuth2Service {
return UUID.randomUUID().toString().replaceAll("-", "");
}
}
}

View File

@@ -26,4 +26,11 @@
AND valid = 1
</update>
</mapper>
<update id="updateToInvalidByRefreshToken" parameterType="String">
UPDATE oauth2_access_token
SET valid = 0
WHERE refresh_token = #{refreshToken}
AND valid = 1
</update>
</mapper>

View File

@@ -17,4 +17,11 @@
AND valid = 1
</update>
</mapper>
<select id="selectById" parameterType="String" resultType="OAuth2RefreshTokenDO">
SELECT
id, user_id, valid, expires_time, create_time
FROM oauth2_refresh_token
WHERE id = #{id}
</select>
</mapper>