以下文章来源Java架构师技术,回复”Spring“获惊喜礼包
大家好,我是Java架构师

⼀、开放接⼝设计说明:

为每个合作机构创建对应的appid、app_secret,⽣成对应的access_token(有效期2⼩时),在调⽤外⽹开放接⼝的时候,必须传递有。
效的access_token。

使⽤ access_token 验证通过才能正常调⽤开放的 API 接⼝
  • appid 是每个⽤户唯⼀的
  • app_secret 可以开发着平台更改
  • access_token 通过 appid + app_secret ⽣成,(有效期2⼩时)
如:微信公众号开发调⽤微信接⼝,下⾯就⾃⼰写⼀个类似于微信开发的api 开放接⼝平台
使⽤流程:同调⽤第三⽅平台接⼝
  1. api 开发平台申请appid ,app_secret ,或⾃⾏提供给消费⽅
  2. 消费⽅通过 appid ,app_secret 获得 access_token ( 有效期2⼩时)
  3. 消费⽅调⽤接⼝携带 accessToken 参数,验证通过可以才访问接⼝,未提供返回错误信息

⼆、数据库表设计 (已下为核⼼字段,更多⾃⾏添加)

App_Name          表⽰机构名称

App_ID            应⽤id

App_Secret        应⽤密钥(可更改)

Is_flag           是否可⽤(是否对某个机构开放)

access_token      上⼀次access_token

CREATETABLE`m_app`
 (

`id`int
(
11
NOTNULL
 AUTO_INCREMENT,

`app_name`varchar
(
255
DEFAULTNULL
,

`app_id`varchar
(
255
DEFAULTNULL
,

`app_secret`varchar
(
255
DEFAULTNULL
,

`is_flag`varchar
(
255
DEFAULTNULL
,

`access_token`varchar
(
255
DEFAULTNULL
,

  PRIMARY 
KEY
 (
`id`
)

ENGINE
=
InnoDB
 AUTO_INCREMENT=
2DEFAULTCHARSET
=utf8;

三、Token⽣成⼯具类TokenUtils

publicclassTokenUtils
{

@RequestMapping
(
"/getToken"
)

publicstatic String getAccessToken()
{

return
 UUID.randomUUID().toString().replace(
"-"
""
);

 }

}

四、getAccessToken 接⼝⽣成 accessToken

步骤:
  1. 调⽤接⼝传递 appId+appSecret
  2. 判断是否存在商户信息
  3. 判断商户信息是否有权限
  4. ⽣成AccessToke,根据当前appId 商户更新最新的 accessToke 到数据库
  5. 删除Redis 上次⽣成的AccessToke缓存,保存最新的accessToke到Redis
import
 org.springframework.beans.factory.
annotation
.Autowired;

import
 org.springframework.web.bind.
annotation
.RequestMapping;

import
 org.springframework.web.bind.
annotation
.RestController;

import
 com.alibaba.fastjson.JSONObject;

import
 com.itmayiedu.base.BaseApiService;

import
 com.itmayiedu.base.ResponseBase;

import
 com.itmayiedu.entity.AppEntity;

import
 com.itmayiedu.mapper.AppMapper;

import
 com.itmayiedu.utils.BaseRedisService;

import
 com.itmayiedu.utils.TokenUtils;


@RestController
@RequestMapping(value = "/auth")
publicclassAuthControllerextendsBaseApiService
{

/**

     * Redis

     */

@Autowired
private
 BaseRedisService baseRedisService;

/**

     * 创建的表appEntity ,的 dao对象

     */

@Autowired
private
 AppMapper appMapper;

/**

     * 过期时间,单位秒

     */

private
 long timeToken = 
60
 * 
60
 * 
2
;

/**

     * TODO    使⽤appId+appSecret ⽣成AccessToke

     * 
@param
 appEntity

     * 
@date
  2019/12/3 0003 21:33

     * 
@return
 com.itmayiedu.base.ResponseBase

     */

@RequestMapping("/getAccessToken")
public
 ResponseBase getAccessToken(AppEntity appEntity) {

// 使⽤appId + appSecret查询
        AppEntity appResult = appMapper.findApp(appEntity);

// 判断是否存在商户信息,等同与微信开发平台申请的appid,appSecret信息是否正确
if
 (appResult == 
null
) {

return
 setResultError(
"没有对应机构的认证信息"
);

        }

//判断是否开发权限给该商户
        int isFlag = appResult.getIsFlag();

if
 (isFlag == 
1
) {

return
 setResultError(
"您现在没有权限⽣成对应的AccessToken"
);

        }

// 从redis中删除之前的accessToken
        baseRedisService.delKey(appResult.getAccessToken());

// ⽣成的新的accessToken 保存到 Redis,并保存到数据库
        String newAccessToken = newAccessToken(appResult.getAppId());

//返回 accessToken,setResultSuccessData为封装返回信息,请⾃定义
        JSONObject jsonObject = new JSONObject();

        jsonObject.put(
"accessToken"
, newAccessToken);

return
 setResultSuccessData(jsonObject);

    }

/**

     * TODO

     * 
@param
 appId

     * 
@date
  2019/12/3 0003 21:33

     * 
@return
 java.lang.String

     */

private
 String newAccessToken(String appId) {

// 使⽤ appid+appsecret ⽣成对应的AccessToken , 保存两个⼩时
        String accessToken = TokenUtils.getAccessToken();

// 保证在同⼀个事物redis 事物中
// ⽣成最新的token, key=accessToken ,value=appid
        baseRedisService.setString(accessToken, appId, timeToken);

// 表数据更新为最新的 accessToken,删除之前的accessToken使⽤
        appMapper.updateAccessToken(accessToken, appId);

return
 accessToken;

    }

}

五、添加拦截器AccessTokenInterceptor ,判断请求参数 accessToken

统⼀拦截所有开放接⼝的请求,判断accessToken 是否有效
import
 java.io.IOException;

import
 java.io.PrintWriter;

import
 javax.servlet.http.HttpServletRequest;

import
 javax.servlet.http.HttpServletResponse;

import
 org.apache.commons.lang.StringUtils;

import
 org.springframework.beans.factory.annotation.Autowired;

import
 org.springframework.stereotype.Component;

import
 org.springframework.web.servlet.HandlerInterceptor;

import
 org.springframework.web.servlet.ModelAndView;

import
 org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import
 com.alibaba.fastjson.JSONObject;

import
 com.fasterxml.jackson.databind.deser.Deserializers.Base;

import
 com.itmayiedu.base.BaseApiService;

import
 com.itmayiedu.utils.BaseRedisService;

/**

 * TODO    验证AccessToken 是否正确

 *

 * 
@date
 2019/12/3 0003 21:54

 * 
@return
 */

@Component
publicclassAccessTokenInterceptorextendsBaseApiServiceimplementsHandlerInterceptor
{

/**

     * redis

     */

@Autowired
private
 BaseRedisService baseRedisService;

/**

     * 进⼊controller层之前拦截请求

     *

     * 
@param
 httpServletRequest

     * 
@param
 httpServletResponse

     * 
@param
 o

     * 
@return
     * 
@throws
 Exception

     */

publicbooleanpreHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
throws
 Exception 
{

        System.out.println(
"---------------------开始进⼊请求地址拦截----------------------------"
);

//获取到accessToken
        String accessToken = httpServletRequest.getParameter(
"accessToken"
);

// 判断accessToken是否空
if
 (StringUtils.isEmpty(accessToken)) {

// 返回错误消息
            resultError(
" this is parameter accessToken null "
, httpServletResponse);

returnfalse
;

        }

//从redis 中获取获取到accessToken
        String appId = (String) baseRedisService.getString(accessToken);

if
 (StringUtils.isEmpty(appId)) {

// accessToken 已经失效!
            resultError(
" this is  accessToken Invalid "
, httpServletResponse);

returnfalse
;

        }

// 正常执⾏业务逻辑...
returntrue
;

    }

publicvoidpostHandle
(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,

                           ModelAndView modelAndView)
throws Exception 
{

                           ModelAndView modelAndView) 
throws
 Exception {

        System.out.println(
"--------------处理请求完成后视图渲染之前的处理操作---------------"
);

    }

publicvoidafterCompletion
(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,

                                Object o, Exception e)
throws Exception 
{

        System.out.println(
"---------------视图渲染之后的操作-------------------------0"
);

    }

/**

     * TODO    返回错误提⽰

     * 
@param
 errorMsg

     * 
@param
 httpServletResponse

     * 
@date
  2019/12/3 0003 21:58

     * 
@return
 void

     */

publicvoidresultError(String errorMsg, HttpServletResponse httpServletResponse)throws IOException 
{

        PrintWriter printWriter = httpServletResponse.getWriter();

// setResultError为封装的返回信息,请⾃定义
        printWriter.write(
new
 JSONObject().toJSONString(setResultError(errorMsg)));

    }

六、添加拦截器AccessTokenInterceptor 的拦截范围

添加拦截器AccessTokenInterceptor 的拦截范围

/openApi 下的所有接⼝
import
 org.springframework.beans.factory.
annotation
.Autowired;

import
 org.springframework.context.
annotation
.Bean;

import
 org.springframework.context.
annotation
.Configuration;

import
 org.springframework.web.servlet.config.
annotation
.InterceptorRegistry;

import
 org.springframework.web.servlet.config.
annotation
.WebMvcConfigurer;

import
 org.springframework.beans.factory.
annotation
.Autowired;

import
 org.springframework.context.
annotation
.Bean;

import
 org.springframework.context.
annotation
.Configuration;

import
 org.springframework.web.servlet.config.
annotation
.InterceptorRegistry;

import
 org.springframework.web.servlet.config.
annotation
.WebMvcConfigurer;

@Configuration
publicclassWebAppConfig
{

@Autowired
private
 AccessTokenInterceptor accessTokenInterceptor;

@Bean
public
 WebMvcConfigurer WebMvcConfigurer() {

return
 new WebMvcConfigurer() {

public
 void addInterceptors(InterceptorRegistry registry) {

//  /openApi   下的所有接⼝
    registry.addInterceptor(accessTokenInterceptor).addPathPatterns(
"/openApi/*"
);

   };

  };

 }

}

使⽤流程:同调⽤第三⽅平台接⼝
  1. api 开发平台申请appid ,app_secret ,或⾃⾏提供给消费⽅
  2. 消费⽅通过 appid ,app_secret 获得 access_token ( 有效期2⼩时)
  3. 消费⽅调⽤接⼝携带 accessToken 参数,验证通过可以才访问接⼝,未提供返回错误信息
欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️
在 程序员小乐 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!
最后,整理了400多套项目,赠送读者。扫码下方二维码,后台回复赚钱即可获取。
--END--
继续阅读
阅读原文