欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot后端實現(xiàn)小程序微信登錄功能實現(xiàn)

 更新時間:2025年05月19日 15:22:18   作者:就叫年華吧丶  
微信小程序登錄是開發(fā)者通過微信提供的身份驗證機(jī)制,獲取用戶唯一標(biāo)識(openid)和會話密鑰(session_key)的過程,這篇文章給大家介紹SpringBoot后端實現(xiàn)小程序微信登錄功能實現(xiàn),感興趣的朋友跟隨小編一起看看吧

SpringBoot實現(xiàn)微信小程序登錄簡介

微信小程序登錄是開發(fā)者通過微信提供的身份驗證機(jī)制,獲取用戶唯一標(biāo)識(openid)和會話密鑰(session_key)的過程。SpringBoot作為后端框架,可以與小程序前端配合完成完整的登錄流程。

小程序端調(diào)用wx.login()

小程序前端調(diào)用此API獲取臨時登錄憑證code

示例代碼:

wx.login({
  success(res) {
    if (res.code) {
      // 發(fā)送code到后端
    }
  }
})

SpringBoot后端處理登錄

接收小程序傳來的code

向微信接口服務(wù)發(fā)起請求驗證code

獲取用戶唯一標(biāo)識openid和會話密鑰session_key

返回自定義登錄態(tài)

后端生成自定義登錄態(tài)(如token)并返回給小程序

小程序后續(xù)請求攜帶此登錄態(tài)

SpringBoot后端實現(xiàn)微信登錄

1.導(dǎo)入HttpClient的Maven坐標(biāo)

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

2.Http工具類

/**
 * Http工具類
 */
public class HttpClientUtil {
?
    static final  int TIMEOUT_MSEC = 5 * 1000;
?
    /**
     * 發(fā)送GET方式請求
     * @param url
     * @param paramMap
     * @return
     */
    public static String doGet(String url,Map<String,String> paramMap){
        // 創(chuàng)建Httpclient對象
        CloseableHttpClient httpClient = HttpClients.createDefault();
?
        String result = "";
        CloseableHttpResponse response = null;
?
        try{
            URIBuilder builder = new URIBuilder(url);
            if(paramMap != null){
                for (String key : paramMap.keySet()) {
                    builder.addParameter(key,paramMap.get(key));
                }
            }
            URI uri = builder.build();
?
            //創(chuàng)建GET請求
            HttpGet httpGet = new HttpGet(uri);
?
            //發(fā)送請求
            response = httpClient.execute(httpGet);
?
            //判斷響應(yīng)狀態(tài)
            if(response.getStatusLine().getStatusCode() == 200){
                result = EntityUtils.toString(response.getEntity(),"UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                response.close();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
?
        return result;
    }
?
    /**
     * 發(fā)送POST方式請求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> paramMap) throws IOException {
        // 創(chuàng)建Httpclient對象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
?
        try {
            // 創(chuàng)建Http Post請求
            HttpPost httpPost = new HttpPost(url);
?
            // 創(chuàng)建參數(shù)列表
            if (paramMap != null) {
                List<NameValuePair> paramList = new ArrayList();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
                }
                // 模擬表單
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
?
            httpPost.setConfig(builderRequestConfig());
?
            // 執(zhí)行http請求
            response = httpClient.execute(httpPost);
?
            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
?
        return resultString;
    }
?
    /**
     * 發(fā)送POST方式請求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
        // 創(chuàng)建Httpclient對象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
?
        try {
            // 創(chuàng)建Http Post請求
            HttpPost httpPost = new HttpPost(url);
?
            if (paramMap != null) {
                //構(gòu)造json格式數(shù)據(jù)
                JSONObject jsonObject = new JSONObject();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    jsonObject.put(param.getKey(),param.getValue());
                }
                StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
                //設(shè)置請求編碼
                entity.setContentEncoding("utf-8");
                //設(shè)置數(shù)據(jù)類型
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
?
            httpPost.setConfig(builderRequestConfig());
?
            // 執(zhí)行http請求
            response = httpClient.execute(httpPost);
?
            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
?
        return resultString;
    }
    private static RequestConfig builderRequestConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(TIMEOUT_MSEC)
                .setConnectionRequestTimeout(TIMEOUT_MSEC)
                .setSocketTimeout(TIMEOUT_MSEC).build();
    }
?
}

3.JWT工具類

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
?
public class JwtUtil {
    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘鑰
     *
     * @param secretKey jwt秘鑰
     * @param ttlMillis jwt過期時間(毫秒)
     * @param claims    設(shè)置的信息
     * @return
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定簽名的時候使用的簽名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
?
        // 生成JWT的時間
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);
?
        // 設(shè)置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有聲明,一定要先設(shè)置這個自己創(chuàng)建的私有的聲明,這個是給builder的claim賦值,一旦寫在標(biāo)準(zhǔn)的聲明賦值之后,就是覆蓋了那些標(biāo)準(zhǔn)的聲明的
                .setClaims(claims)
                // 設(shè)置簽名使用的簽名算法和簽名使用的秘鑰
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 設(shè)置過期時間
                .setExpiration(exp);
?
        return builder.compact();
    }
?
    /**
     * Token解密
     *
     * @param secretKey jwt秘鑰 此秘鑰一定要保留好在服務(wù)端, 不能暴露出去, 否則sign就可以被偽造, 如果對接多個客戶端建議改造成多個
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 設(shè)置簽名的秘鑰
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 設(shè)置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }
?
}

4.準(zhǔn)備好簽名所需使用的密鑰,過期時間等

sky:
  jwt:
    user-secret-key: itcast
    # 設(shè)置jwt過期時間
    user-ttl: 7200000
    # 設(shè)置前端傳遞過來的令牌名稱
    user-token-name: authentication

5.用對象類將配置文件的屬性封裝

@Component
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {
    /**
     * 用戶端微信用戶生成jwt令牌相關(guān)配置
     */
    private String userSecretKey;
    private long userTtl;
    private String userTokenName;
?
}

6.WeChatProperties對象類部分屬性以及配置文件

關(guān)于怎么注冊大家可以移步最下方。

@Component
@ConfigurationProperties(prefix = "sky.wechat")
@Data
public class WeChatProperties {
?
    private String appid; //小程序的appid
    private String secret; //小程序的秘鑰
?
}
?
//application.yml配置文件
sky:
  wechat:
    appid: ${sky.wechat.appid}
    secret: ${sky.wechat.secret}
?
//application-dev.yml配置文件
sky:
  wechat:
#   TODO:需要在微信公眾平臺申請相關(guān)信息并填入
    appid: ******
    secret: ******

7.準(zhǔn)備好DTO數(shù)據(jù)對象

/**
 * C端用戶登錄
 */
@Data
public class UserLoginDTO implements Serializable {
?
    private String code;
?
}

8.控制層接口

@RestController
@RequestMapping("/user/user")
@Slf4j
@RequiredArgsConstructor  // Lombok 自動生成構(gòu)造函數(shù)
@Api(tags = "C端用戶相關(guān)接口")
public class UserController {
    private final UserService userService;
    private final JwtProperties jwtProperties;
    /**
     * 微信登錄
     * @param userLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation("微信登錄")
    public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
        log.info("微信用戶登錄:{}",userLoginDTO.getCode());
?
        //微信登錄
        User user = userService.wxLogin(userLoginDTO);
?
        //為微信用戶生成jwt令牌
        Map<String,Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID,user.getId());
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(),jwtProperties.getUserTtl(),claims);
?
        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .openid(user.getOpenid())
                .token(token)
                .build();
?
        return Result.success(userLoginVO);
    }
}

9.微信登錄的服務(wù)層的接口和實現(xiàn)類

//接口
public interface UserService {
    /**
     * 微信登錄接口
     * @param userLoginDTO
     * @return
     */
    User wxLogin(UserLoginDTO userLoginDTO);
}
?
//實現(xiàn)類
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
    @Autowired
    private WeChatProperties weChatProperties;
    @Autowired
    private UserMapper userMapper;
?
    /**
     * 微信登錄
     * @param userLoginDTO
     * @return
     */
    @Override
    public User wxLogin(UserLoginDTO userLoginDTO) {
        String openid = getOpenid(userLoginDTO.getCode());
        //判斷openid是否為空,如果為空表示登錄失敗,拋出業(yè)務(wù)異常
        if(openid == null){
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }
?
        //判斷當(dāng)前用戶是否是新用戶
        User user = userMapper.getByOpenid(openid);
?
        //如果是新用戶,自動完成注冊
        if(user == null){
            user = User.builder()
                    .openid(openid)
                    .createTime(LocalDateTime.now())
                    .build();
            userMapper.insert(user);
        }
        //返回這個用戶對象
?
        return user;
    }
?
    /**
     * 調(diào)用微信接口服務(wù),獲取當(dāng)前微信用戶的openid
     * @param code
     * @return
     */
    private String getOpenid(String code){
        Map<String, String> map = new HashMap<>();
        map.put("appid",weChatProperties.getAppid());
        map.put("secret",weChatProperties.getSecret());
        map.put("js_code",code);
        map.put("grant_type","authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN, map);
?
        JSONObject jsonObject =JSON.parseObject(json);
        String openid = jsonObject.getString("openid");
?
        return openid;
    }
}
?


注冊小程序,獲取key

微信公眾平臺

到此這篇關(guān)于SpringBoot后端實現(xiàn)小程序微信登錄的文章就介紹到這了,更多相關(guān)SpringBoot小程序微信登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入探究Java線程不安全的原因與解決

    深入探究Java線程不安全的原因與解決

    線程不安全這個問題,一般在學(xué)Java時,我們老師會讓我們背誦一段長長的話。"當(dāng)不同線程同時能訪問同一個變量時,可能會導(dǎo)致線程不安全"。實際上,這句話重點想突出的只有原子性。而我們往往考慮線程不安全的原因,會從三方面進(jìn)行考慮:就是原子性,可見性,有序性
    2022-04-04
  • JAVA截取字符串的幾種常用方法

    JAVA截取字符串的幾種常用方法

    這篇文章主要給大家介紹了關(guān)于JAVA截取字符串的幾種常用方法, 在處理字符串的過程中有很多情況下會遇到需要截取字符串的情況,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 配置springboot項目使用外部tomcat過程解析

    配置springboot項目使用外部tomcat過程解析

    這篇文章主要介紹了配置springboot項目使用外部tomcat過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • Hadoop的安裝與環(huán)境搭建教程圖解

    Hadoop的安裝與環(huán)境搭建教程圖解

    這篇文章主要介紹了Hadoop的安裝與環(huán)境搭建教程圖解,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-06-06
  • java 如何把byte轉(zhuǎn)化為KB、MB、GB的方法

    java 如何把byte轉(zhuǎn)化為KB、MB、GB的方法

    這篇文章主要介紹了java 如何把byte轉(zhuǎn)化為KB、MB、GB的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 使用Java制作一個簡單的記事本

    使用Java制作一個簡單的記事本

    本文給大家?guī)淼氖鞘褂肑ava制作一個簡單的記事本的代碼,有相同需要的朋友可以參考下
    2015-02-02
  • Java后端實現(xiàn)短鏈接生成功能

    Java后端實現(xiàn)短鏈接生成功能

    短鏈接生成主要在于把指定的接口和參數(shù)實現(xiàn)加密生成比較短的字符串,再進(jìn)行拼接通過指定的域名或者ip實現(xiàn)鏈接的跳轉(zhuǎn),下面我們來看看如何使用Java實現(xiàn)這一功能吧
    2025-03-03
  • Spring配置與依賴注入基礎(chǔ)詳解

    Spring配置與依賴注入基礎(chǔ)詳解

    依賴注入(Dependency?Injection)和控制反轉(zhuǎn)(Inversion?of?Control)是同一個概念。具體含義是:當(dāng)某個角色(可能是一個Java實例,調(diào)用者)需要另一個角色(另一個Java實例,被調(diào)用者)的協(xié)助時,在?傳統(tǒng)的程序設(shè)計過程中,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實例
    2022-08-08
  • java條件語句示例詳解

    java條件語句示例詳解

    本文給大家介紹java條件語句,Java 中的條件語句允許程序根據(jù)條件的不同執(zhí)行不同的代碼塊,一個 if 語句包含一個布爾表達(dá)式和一條或多條語句,本文結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • SpringBoot基于自定義注解實現(xiàn)切面編程

    SpringBoot基于自定義注解實現(xiàn)切面編程

    這篇文章主要介紹了SpringBoot基于自定義注解實現(xiàn)切面編程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11

最新評論