idea搭建SSM+TOKEN+Swagger-ui+Mysql

環(huán)境配置

JDK:1.8 MAVEN:3.6.1 IDE:19.3 TOMCAT:8 MYSQL:5.7 swagger-ui2

基本框架搭建

可參考本人博客地址

https://blog.csdn.net/qq_41998978/article/details/103362147

添加TOKEN驗(yàn)證

pom.xml文件加入以下

<!-- jwt -->
    <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>2.2.0</version>
    </dependency>

JWT加密解密工具類

/**
 * 項(xiàng)目名:AutomobileModelTradingPlatform
 * 日 期:2020/2/9
 * 包 名:com.item.utile
 *
 * @author: LiuJia
 * Copyright 2019 403
 */
package com.item.utile;
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;

public class JWT {
    private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

    private static final String EXP = "exp";

    private static final String PAYLOAD = "payload";

    //加密,傳入一個(gè)對(duì)象和有效期
    public static <T> String sign(T object, long maxAge) {
        try {
            final JWTSigner signer = new JWTSigner(SECRET);
            final Map<String, Object> claims = new HashMap<String, Object>();
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(object);
            claims.put(PAYLOAD, jsonString);
            claims.put(EXP, System.currentTimeMillis() + maxAge);
            return signer.sign(claims);
        } catch(Exception e) {
            return null;
        }
    }

    //解密,傳入一個(gè)加密后的token字符串和解密后的類型
    public static<T> T unsign(String jwt, Class<T> classT) {
        final JWTVerifier verifier = new JWTVerifier(SECRET);
        try {
            final Map<String,Object> claims= verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                long exp = (Long)claims.get(EXP);
                long currentTimeMillis = System.currentTimeMillis();
                if (exp > currentTimeMillis) {
                    String json = (String)claims.get(PAYLOAD);
                    ObjectMapper objectMapper = new ObjectMapper();
                    return objectMapper.readValue(json, classT);
                }
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
}

SSM中攔截器判斷TOKEN工具類

/**
 * 項(xiàng)目名:AutomobileModelTradingPlatform
 * 日 期:2020/2/4
 * 包 名:com.item.utile
 *
 * @author: LiuJia
 * Copyright 2019 403
 */
package com.item.utile;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.item.entity.Adminuser;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;

public class TokenInterceptor implements HandlerInterceptor {

    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception arg3)
            throws Exception {
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView model) throws Exception {
    }

    //攔截每個(gè)請(qǐng)求
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        response.setCharacterEncoding("utf-8");
        //讀取請(qǐng)求頭中的Token信息
        String token = request.getHeader("token");
        //判斷token是否存在
        if (null != token) {
            //獲取token中的實(shí)體類信息
            Adminuser adminuser = JWT.unsign(token, Adminuser.class);
            //獲取請(qǐng)求頭中用戶id信息
            String userId = request.getHeader("userId");
            //判斷token是否合法
            if (null != userId && null != adminuser) {
                //解密token后得到的用戶id和請(qǐng)求頭中的用戶對(duì)比
                if (Integer.parseInt(userId) == adminuser.getId()) {
                    return true;
                } else {
                    //這里的ResponseData是包裝的json工具類
                    ResponseData responseData = ResponseData.customerError("token已過期");
                    responseMessage(response, response.getWriter(), responseData);
                    return false;
                }
            } else {
                ResponseData responseData = ResponseData.customerError("token無效");
                responseMessage(response, response.getWriter(), responseData);
                return false;
            }
        } else {
            ResponseData responseData = ResponseData.customerError("無token");
            responseMessage(response, response.getWriter(), responseData);
            return false;
        }
    }

    //請(qǐng)求不通過,返回錯(cuò)誤信息給客戶端
    private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
        response.setContentType("application/json; charset=utf-8");
        String json = JSONObject.toJSONString(responseData);
        out.print(json);
        out.flush();
        out.close();
    }
}

spring-mvc.xml配置文件加入攔截器

<mvc:interceptors>
        <mvc:interceptor>
            <!-- 設(shè)置攔截的路徑 -->
            <mvc:mapping path="/Api/**"/>
            <!-- 設(shè)置放開攔截的路徑,這里是登錄 -->
            <mvc:exclude-mapping path="/Api/userApi/login"/>
            <!-- 指定自己的攔截器工具類路徑-->
            <bean class="com.item.utile.TokenInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!--這里配置返回json時(shí)可能出現(xiàn)亂碼。處理亂碼-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/plain;charset=UTF-8"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

用于返回給客戶端的json包裝類

/**
 * 項(xiàng)目名:AutomobileModelTradingPlatform
 * 日 期:2020/2/9
 * 包 名:com.item.utile
 *
 * @author: LiuJia
 * Copyright 2019 xiaojiajia
 */
package com.item.utile;
import java.util.HashMap;
import java.util.Map;

public class ResponseData {
    private final String message;
    private final int code;
    private final Map<String, Object> data = new HashMap<String, Object>();
    public String getMessage() {
        return message;
    }

    public int getCode() {
        return code;
    }

    public Map<String, Object> getData() {
        return data;
    }

    public ResponseData putDataValue(String key, Object value) {
        data.put(key, value);
        return this;
    }

    private ResponseData(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public static ResponseData ok() {
        return new ResponseData(200, "訪問成功");
    }

    public static ResponseData notFound() {
        return new ResponseData(404, "服務(wù)器丟失");
    }

    public static ResponseData badRequest() {
        return new ResponseData(400, "服務(wù)器錯(cuò)誤");
    }

    public static ResponseData forbidden() {
        return new ResponseData(403, "系統(tǒng)錯(cuò)誤");
    }

    public static ResponseData unauthorized() {
        return new ResponseData(401, "未經(jīng)授權(quán)");
    }
    
    public static ResponseData serverInternalError() {
        return new ResponseData(500, "服務(wù)器內(nèi)部錯(cuò)誤");
    }
    
    public static ResponseData customerError(String message) {
        return new ResponseData(1001, message);
    }
}

處理登錄

    @RequestMapping("/login")
    public Object login(String userName, String userPwd) {
        //這里采用的是封裝工具查詢,此處不做說明
        AdminuserExample adminuserExample = new AdminuserExample();
        AdminuserExample.Criteria criteria = adminuserExample.createCriteria();
        criteria.andAdminusercodeEqualTo(userName);
        List<Adminuser> adminuserList = adminuserService.selectByExample(adminuserExample);
        if (adminuserList.size() > 0) {
            if (adminuserList.get(0).getAdminuserpwd().equals(userPwd)) {
                //登錄成功
                //生成加密token
                String token = JWT.sign(adminuserList.get(0), 60L * 1000L * 30L);
                //返回給客戶端的信息
                ResponseData responseData = ResponseData.ok();
                responseData.putDataValue("userId", adminuserList.get(0).getId());
                responseData.putDataValue("token", token);
                responseData.putDataValue("user", adminuserList.get(0));
                return responseData;
            } else {
                ResponseData responseData = ResponseData.customerError("密碼錯(cuò)誤");
                return responseData;
            }
        } else {
            ResponseData responseData = ResponseData.customerError("無效用戶名");
            return responseData;
        }
    }

驗(yàn)證說明:在之后請(qǐng)求接口時(shí),前端需要在請(qǐng)求頭中帶上“userId”和“token”兩個(gè)參數(shù),解密token后和前端傳來的用戶id對(duì)比,以此判斷token的合法性。

加入Swagger-ui接口文檔

pom.xml文件加入

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
    </dependency>

SwaggerConfiguration工具類

/**
 * 項(xiàng)目名:eep
 * 日  期:2020/2/10
 * 包  名:com.item.utile
 *
 * @author: Liujia
 * Copyright 2019 xiaojiajiaK3
 */

package com.item.utile;

import com.google.common.collect.Lists;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

import static springfox.documentation.builders.PathSelectors.regex;

@Configuration
@EnableSwagger2
//@Profile({"prod"})
public class SwaggerConfiguration {
    @Bean
    public Docket platformApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).forCodeGeneration(true)
                .select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(regex("^.*(?<!error)$"))
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .pathMapping("/")
                ;
    }
    private List<ApiKey> securitySchemes() {
        return Lists.newArrayList(
                //這里配置兩個(gè)全局頭請(qǐng)求-跟上面token驗(yàn)證配套
                new ApiKey("token", "token", "header"),
                new ApiKey("userId", "userId", "header")
        );
    }
    
    private List<SecurityContext> securityContexts() {
        return Lists.newArrayList(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .build()
        );
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "認(rèn)證權(quán)限");
        return Lists.newArrayList(
                //這里配置兩個(gè)頭請(qǐng)求-每個(gè)接口-跟上面token驗(yàn)證配套
                new SecurityReference("token", new AuthorizationScope[]{authorizationScope}),
                new SecurityReference("userId", new AuthorizationScope[]{authorizationScope})
        );
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("xxx平臺(tái)接口文檔").description("?xiaojiajiaK3")
                .termsOfServiceUrl("https://blog.csdn.net/qq_41998978")
                .contact(new Contact("xxx交易平臺(tái)", "", "xiaojiajia981225@outlook.com")).license("Apache License Version 2.0")
                .licenseUrl("https://blog.csdn.net/qq_41998978").version("2.0").build();
    }
}

spring-mvc.xml配置文件加入

    <!-- 加載SwaggerConfig  類名改成自己創(chuàng)建的-->
    <bean class="com.item.utile.SwaggerConfiguration"/>
    
    <!-- 將靜態(tài)資源交由默認(rèn)的servlet處理--沒有這句的加上這句 -->
    <mvc:default-servlet-handler/>

使用

//控制器加入
@Api(tags = "xxx接口")
//方法加入
@ApiOperation(value="xxx接口",notes = "這是notes描述",httpMethod = "GET--請(qǐng)求方式")

注意事項(xiàng)

//這些注解用于解決跨域訪問的問題
@RestController
@CrossOrigin
//web.xml文件中若沒有以下配置要加上
    <servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <!-- 匹配所有請(qǐng)求,此處也可以配置成 *.do 形式 -->
    <!--/*.do是對(duì)所有以.do結(jié)尾的請(qǐng)求做處理,/*是對(duì)所有請(qǐng)求做處理-->
    <url-pattern>/</url-pattern>
    </servlet-mapping>

效果圖

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374