最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot常見登錄(注冊(cè))幾種實(shí)現(xiàn)過程

 更新時(shí)間:2026年02月11日 08:52:53   作者:zhm_sky  
這篇文章主要介紹了如何實(shí)現(xiàn)用戶注冊(cè)、登錄和微信掃碼登錄功能,注冊(cè)功能通過手機(jī)號(hào)和短信驗(yàn)證碼完成,登錄功能通過賬號(hào)密碼和微信掃碼兩種方式實(shí)現(xiàn),并使用JWT進(jìn)行單點(diǎn)登錄

一、用戶注冊(cè)(手機(jī)驗(yàn)證碼)

目前主流采用手機(jī)號(hào)注冊(cè)方式,因?yàn)槭占绞謾C(jī)號(hào)對(duì)用戶推廣、業(yè)務(wù)推廣有極其重要的價(jià)值。結(jié)合上篇采用阿里云短信服務(wù)實(shí)現(xiàn)手機(jī)驗(yàn)證碼的發(fā)送,這里整合實(shí)現(xiàn)用手機(jī)號(hào)實(shí)現(xiàn)用戶注冊(cè)。

思路:前端在輸入手機(jī)號(hào)之后,需要對(duì)手機(jī)號(hào)進(jìn)行校驗(yàn),用戶需要接收短信驗(yàn)證碼并完成驗(yàn)證碼校驗(yàn)之后即可成功注冊(cè)。具體步驟:

  • 1、判斷當(dāng)前手機(jī)號(hào)是否已注冊(cè);
  • 2、調(diào)用阿里云短信服務(wù)api實(shí)現(xiàn)驗(yàn)證碼發(fā)送;
  • 3、驗(yàn)證碼發(fā)送成功并存放至redis緩存,利用緩存淘汰機(jī)制(設(shè)置有效時(shí)間)實(shí)現(xiàn)驗(yàn)證碼過期;
  • 4、驗(yàn)證碼校驗(yàn),通過即注冊(cè)成功。

1.1 用戶實(shí)體類

package com.zhmsky.service_ucenter.entity;

import com.baomidou.mybatisplus.annotation.*;

import java.util.Date;

import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 會(huì)員表
 * </p>
 *
 * @author zhmsky
 * @since 2022-07-16
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="UcenterMember對(duì)象", description="會(huì)員表")
public class UcenterMember implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "會(huì)員id")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;

    @ApiModelProperty(value = "微信openid")
    private String openid;

    @ApiModelProperty(value = "手機(jī)號(hào)")
    private String mobile;

    @ApiModelProperty(value = "密碼")
    private String password;

    @ApiModelProperty(value = "昵稱")
    private String nickname;

    @ApiModelProperty(value = "性別 1 女,2 男")
    private Integer sex;

    @ApiModelProperty(value = "年齡")
    private Integer age;

    @ApiModelProperty(value = "用戶頭像")
    private String avatar;

    @ApiModelProperty(value = "用戶簽名")
    private String sign;

    @ApiModelProperty(value = "是否禁用 1(true)已禁用,  0(false)未禁用")
    private Boolean isDisabled;

    @ApiModelProperty(value = "邏輯刪除 1(true)已刪除, 0(false)未刪除")
    private Boolean isDeleted;

    @ApiModelProperty(value = "創(chuàng)建時(shí)間")
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @ApiModelProperty(value = "更新時(shí)間")
    @TableField(fill = FieldFill.UPDATE)
    private Date updateTime;

}

1.2 注冊(cè)用戶視圖對(duì)象

package com.zhmsky.service_ucenter.entity.VO;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author zhmsky
 * @date 2022/7/16 17:18
 */
@Data
@ApiModel(value="注冊(cè)對(duì)象", description="注冊(cè)對(duì)象")
public class RegisterVO {

    @ApiModelProperty(value = "昵稱")
    private String nickname;

    @ApiModelProperty(value = "手機(jī)號(hào)")
    private String mobile;

    @ApiModelProperty(value = "密碼")
    private String password;

    @ApiModelProperty(value = "驗(yàn)證碼")
    private String code;
}

1.3 短信驗(yàn)證碼的發(fā)送

調(diào)用阿里云短信服務(wù)實(shí)現(xiàn)短信驗(yàn)證碼發(fā)送

package com.zhmsky.msmService.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.zhmsky.msmService.service.MsmService;
import org.springframework.stereotype.Service;

/**
 * @author zhmsky
 * @date 2022/7/6 21:01
 * 短信驗(yàn)證碼實(shí)現(xiàn)類
 */
@Service
public class MsmServiceImpl implements MsmService {

    /**
     * 發(fā)送短信驗(yàn)證碼
     * @param phone 手機(jī)號(hào)
     * @param code 被發(fā)送的驗(yàn)證碼
     * @return
     */
    @Override
    public String sendCodeMsg(String phone, String code) {
        String checkCode="";
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI5tDfHQPQ5WA5dBkrfFxu", "eRID7ZigveAH7fMRKbCDq92jjRl68R");


        IAcsClient client = new DefaultAcsClient(profile);

        SendSmsRequest request = new SendSmsRequest();
        request.setSignName("阿里云短信測(cè)試");
        request.setTemplateCode("SMS_154950909");
        request.setPhoneNumbers(phone);
        request.setTemplateParam("{\"code\":\""+code+"\"}");

        try {
            SendSmsResponse response = client.getAcsResponse(request);
            checkCode = response.getCode();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
        return checkCode;
    }
}

短信驗(yàn)證碼發(fā)送接口

package com.zhmsky.msmService.controller;

import com.zhmsky.msmService.service.MsmService;
import com.zhmsky.msmService.utils.RandomUtil;
import com.zhmsky.result.Result;
import com.zhmsky.result.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhmsky
 * @date 2022/7/6 20:58
 */
@RestController
@Api("短信注冊(cè)控制器")
@CrossOrigin
@RequestMapping("/msmService")
public class MsmController {

    @Autowired
    private MsmService msmService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @GetMapping("/send/{phone}")
    @ApiOperation("發(fā)送短信驗(yàn)證碼")
    public Result<String> sendMsg(@PathVariable String phone){
        //通過redis設(shè)置緩存時(shí)間實(shí)現(xiàn)驗(yàn)證碼過期
        String code = redisTemplate.opsForValue().get(phone);
        if(!StringUtils.isEmpty(code)){
            return new ResultUtil<String>().setSuccessMsg("請(qǐng)勿重復(fù)發(fā)送!");
        }
        /**  如果緩存里面沒有那么就重新發(fā)送   **/
        //生成隨機(jī)驗(yàn)證碼
        String fourBitRandom = RandomUtil.getFourBitRandom();
        //調(diào)用阿里云api實(shí)現(xiàn)短信發(fā)送
        String checkCode = msmService.sendCodeMsg(phone, fourBitRandom);
        if("OK".equals(checkCode)){
            //將驗(yàn)證碼保存到redis中并設(shè)置有效時(shí)間為5分鐘
            redisTemplate.opsForValue().set(phone,fourBitRandom,5, TimeUnit.MINUTES);
            return new ResultUtil<String>().setData(fourBitRandom,"驗(yàn)證碼發(fā)送成功!");
        }else{
            return new ResultUtil<String>().setErrorMsg("驗(yàn)證碼發(fā)送給失敗!");
        }
    }

}

1.4 注冊(cè)功能實(shí)現(xiàn)

  • 1、接口保護(hù),參數(shù)非空判斷;
  • 2、驗(yàn)證手機(jī)號(hào)是否已注冊(cè);
  • 3、驗(yàn)證碼校驗(yàn);
  • 4、入庫
 /**
     * 用戶注冊(cè)
     * @param registerVO
     * @return
     */
    @Override
    public boolean register(RegisterVO registerVO) {
        //獲取注冊(cè)數(shù)據(jù),接口保護(hù),參數(shù)校驗(yàn)
        String code = registerVO.getCode();
        String mobile = registerVO.getMobile();
        String nickname = registerVO.getNickname();
        String password = registerVO.getPassword();

        if(StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)||StringUtils.isEmpty(code)||StringUtils.isEmpty(nickname)){
            throw new MyException(20005,"注冊(cè)失敗!");
        }

        //判斷手機(jī)號(hào)是否已注冊(cè)
        QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile",mobile);
        Long count = baseMapper.selectCount(wrapper);
        if(count>0){
            throw new MyException(20005,"注冊(cè)失敗!");
        }

        //驗(yàn)證碼校驗(yàn)
        //先從redis中獲取驗(yàn)證碼
        String cacheCode = redisTemplate.opsForValue().get(mobile);
        if(!code.equals(cacheCode)){
           throw new MyException(20005,"注冊(cè)失敗!");
        }

        //入庫
        UcenterMember ucenterMember = new UcenterMember();
        ucenterMember.setMobile(mobile);
        ucenterMember.setNickname(nickname);
        ucenterMember.setPassword(MD5.encrypt(password));
        ucenterMember.setIsDisabled(false);
        ucenterMember.setAvatar("http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132");
        int insert = baseMapper.insert(ucenterMember);
        if(insert>0){
            return true;
        }else{
            return false;
        }

    }

二、用戶登錄

2.1 賬號(hào)密碼登錄

登錄流程:

  • 1、調(diào)用登錄接口并返回token字符串
  • 2、將返回的token字符串放到cookie里面
  • 3、創(chuàng)建前端攔截器,判斷cookie里面是否有token字符串,如果有則將token放到request的header中
  • 4、調(diào)用接口,根據(jù)token獲取用戶信息并再次放到cookie中(為了首頁面展示)
  • 5、再從cookie中取出用戶信息進(jìn)行展示

思路:

  • 1、接口保護(hù),參數(shù)非空校驗(yàn);
  • 2、驗(yàn)證賬號(hào)是否注冊(cè);
  • 3、驗(yàn)證賬號(hào)是否禁用;
  • 4、驗(yàn)證密碼;
  • 5、登錄并返回token。

為了實(shí)現(xiàn)單點(diǎn)登錄,采用token令牌方式,引入jwt

jwt工具類:

package com.zhmsky.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author zhmsky
 * @date 2022/7/6 17:53
 */
public class JwtUtils {
    //設(shè)置token過期時(shí)間
    public static final long EXPIRE = 1000 * 60 * 60 * 24;    //一天
    //簽名加密密鑰
    public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";

    /**
     * 生成token
     * @param id
     * @param nickname
     * @return
     */
    public static String getJwtToken(String id, String nickname){

        String JwtToken = Jwts.builder()
                //設(shè)置頭信息
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                //設(shè)置token過期時(shí)間
                .setSubject("user")   //隨便寫
                .setIssuedAt(new Date())
                //當(dāng)前時(shí)間加上設(shè)置的過期時(shí)間
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                //設(shè)置token主體,可存儲(chǔ)用戶信息
                .claim("id", id)
                .claim("nickname", nickname)
                //簽名哈希
                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }

    /**
     * 判斷token是否存在與有效
     * @param jwtToken
     * @return
     */
    public static boolean checkToken(String jwtToken) {
        if(StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判斷token是否存在與有效
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根據(jù)token獲取會(huì)員id
     * @param request
     * @return
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }
}

登錄業(yè)務(wù):

 /**
     * 用戶登錄
     * @param member
     * @return token
     */
    @Override
    public String login(UcenterMember member) {
       //獲取賬號(hào)和密碼
        String mobile = member.getMobile();
        String password = member.getPassword();
       if(StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)){
           throw new MyException(20010,"賬號(hào)和密碼不能為空!");
       }
       //判斷賬號(hào)和密碼是否存在
        QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile",mobile);
        UcenterMember ucenterMember = baseMapper.selectOne(wrapper);
        if(ObjectUtils.isEmpty(ucenterMember)){
            throw new MyException(20011,"賬號(hào)不存在,請(qǐng)重新輸入!");
        }
        //判斷該用戶是否被禁用
        Boolean isDisabled = ucenterMember.getIsDisabled();
        if(isDisabled){
            throw new MyException(20013,"該賬號(hào)已禁用!");
        }
        //判斷密碼是否正確
        //密碼存儲(chǔ)肯定是加密的,實(shí)際開發(fā)中數(shù)據(jù)庫不會(huì)存儲(chǔ)明文密碼
        //先將輸入的密碼加密,再和數(shù)據(jù)庫密碼比較
        //MD5加密
        String realPassword = ucenterMember.getPassword();
        if(!MD5.encrypt(password).equals(realPassword)){
            throw new MyException(20012,"密碼錯(cuò)誤,請(qǐng)重新輸入!");
        }
        //登錄成功,返回token(通過查出來的用戶數(shù)據(jù)去生成token)
        return JwtUtils.getJwtToken(ucenterMember.getId(), ucenterMember.getNickname());
    }

登錄接口:

    @PostMapping ("/login")
    @ApiOperation("用戶登錄")
    public Result<String> login(@RequestBody(required = false) UcenterMember ucenterMember){
        //登錄生成token并返回
        String token = memberService.login(ucenterMember);
        return new ResultUtil<String>().setData(token);
    }

登錄成功后,前端每次請(qǐng)求都攜帶token,從request對(duì)象中獲取token再解析token獲取用戶信息。

    @GetMapping("/getUserInfo")
    @ApiOperation("根據(jù)token獲取用戶信息")
    public Result<UcenterMember> getUserInfo(HttpServletRequest httpServletRequest){
        //從request對(duì)象中獲取token,再根據(jù)token獲取用戶信息
        String userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        //根據(jù)用戶id獲取用戶信息
        UcenterMember ucenterMember = memberService.getById(userId);
        return new ResultUtil<UcenterMember>().setData(ucenterMember);
    }

2.2 微信掃碼登錄

2.2.1 準(zhǔn)備工作

網(wǎng)站應(yīng)用微信登錄是基于OAuth2.0協(xié)議標(biāo)準(zhǔn)構(gòu)建的微信OAuth2.0授權(quán)登錄系統(tǒng)。

在進(jìn)行微信OAuth2.在進(jìn)行微信OAuth2.0授權(quán)登錄接入之前,在微信開放平臺(tái)注冊(cè)開發(fā)者帳號(hào),并擁有一個(gè)已審核通過的網(wǎng)站應(yīng)用,并獲得相應(yīng)的AppID和AppSecret,申請(qǐng)微信登錄且通過審核后,可開始接入流程。

2.2.2 授權(quán)流程

第三方發(fā)起微信授權(quán)登錄請(qǐng)求,微信用戶允許授權(quán)第三方應(yīng)用后,微信會(huì)拉起應(yīng)用或重定向到第三方網(wǎng)站,并且?guī)鲜跈?quán)臨時(shí)票據(jù)code參數(shù);

通過code參數(shù)加上AppID和AppSecret等,通過API換取access_token;

通過access_token進(jìn)行接口調(diào)用,獲取用戶基本數(shù)據(jù)資源或幫助用戶實(shí)現(xiàn)基本操作。

第一步:請(qǐng)求生成微信二維碼

根據(jù)官方文檔,直接請(qǐng)求微信開放平臺(tái)固定地址https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect,其中有4個(gè)必備的參數(shù);

  • appid:微信開放平臺(tái)申請(qǐng)通過后頒發(fā)的唯一標(biāo)識(shí)
  • redirect_uri:微信掃碼授權(quán)后的回調(diào)地址
  • response_type:code
  • scope:授權(quán)作用域,web應(yīng)用直接填snsapi_login即可

準(zhǔn)備好以上參數(shù),在properties文件中完成初始值設(shè)置

wx.open.app_id=wxed9954c01bb89b47
wx.open.app_secret=a7482517235173ddb4083788de60b90e
wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback

編寫參數(shù)初始化工具類:

package com.zhmsky.service_ucenter.utils;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author zhmsky
 * @date 2022/7/17 17:06
 */
@Component
public class ConstWxUtil implements InitializingBean {

    @Value("${wx.open.app_id}")
    private String appId;

    @Value("${wx.open.app_secret}")
    private String appSecret;

    @Value("${wx.open.redirect_url}")
    private String redirectUrl;

    public static String WX_OPEN_APP_ID;
    public static String WX_OPEN_APP_SECRET;
    public static String WX_OPEN_REDIRECT_URL;

    @Override
    public void afterPropertiesSet() throws Exception {
        WX_OPEN_APP_ID = appId;
        WX_OPEN_APP_SECRET = appSecret;
        WX_OPEN_REDIRECT_URL = redirectUrl;
    }
}

二維碼生成接口:

    @GetMapping("/getWxCode")
    @ApiOperation("生成微信二維碼")
    public String getWxCode() {
        // 微信開放平臺(tái)授權(quán)baseUrl
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        // 回調(diào)地址
        String redirectUrl = ConstWxUtil.WX_OPEN_REDIRECT_URL;
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8"); //url編碼
        } catch (UnsupportedEncodingException e) {
            throw new MyException(20001, e.getMessage());
        }
        String state = "imhelen";
        //生成qrcodeUrl
        String qrcodeUrl = String.format(
                baseUrl,
                ConstWxUtil.WX_OPEN_APP_ID,
                redirectUrl,
                state);

        return "redirect:" + qrcodeUrl;
    }

第二步:微信掃碼后執(zhí)行回調(diào)

    @GetMapping("/callback")
    @ApiOperation("微信掃碼確認(rèn)后執(zhí)行回調(diào)")
    public String callback(String code,String state){
        //TODO 
        return "redirect:http://localhost:3000";
    }

再接著

獲取隨機(jī)code,請(qǐng)求微信資源服務(wù)器固定地址拿到accessToken(訪問憑證)和openId(用戶唯一標(biāo)識(shí)),再通過accessToken和openId請(qǐng)求微信資源服務(wù)器固定地址拿到掃碼人的基本信息。獲取到用戶基本信息后就可以進(jìn)行校驗(yàn)完成入庫等操作。

   @GetMapping("/callback")
    @ApiOperation("微信掃碼確認(rèn)后執(zhí)行回調(diào)")
    public String callback(String code,String state){
        //1、接收code值
        //用code去請(qǐng)求微信的固定地址,得到accessToken和openId
        //向認(rèn)證服務(wù)器發(fā)送請(qǐng)求換取access_token
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=%s" +
                "&secret=%s" +
                "&code=%s" +
                "&grant_type=authorization_code";

        //帶參數(shù)的真實(shí)認(rèn)證服務(wù)器請(qǐng)求地址
        String accessTokenUrl = String.format(baseAccessTokenUrl,
                ConstWxUtil.WX_OPEN_APP_ID,
                ConstWxUtil.WX_OPEN_APP_SECRET,
                code
        );
        //2、請(qǐng)求認(rèn)證服務(wù)器獲取接口調(diào)用憑證access_token和用戶唯一標(biāo)識(shí)openId
        try {
            String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
            //將上述json字符串轉(zhuǎn)換成map對(duì)象
            /*
            {
                "access_token":"ACCESS_TOKEN",
                "expires_in":7200,
                "refresh_token":"REFRESH_TOKEN",
                "openid":"OPENID",
                "scope":"SCOPE",
                "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
             }
             */
            Gson gson = new Gson();
            HashMap mapAccessTokenInfo = gson.fromJson(accessTokenInfo, HashMap.class);
            //取出的access_token
            String access_token = (String)mapAccessTokenInfo.get("access_token");
            //取出的openid
            String openid = (String)mapAccessTokenInfo.get("openid");

            //3、再通過獲取出來的access_token和openid去請(qǐng)求微信開放平臺(tái)服務(wù)器獲取掃碼人信息
            //訪問微信的資源服務(wù)器,獲取用戶信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);
            //發(fā)送請(qǐng)求獲取掃碼人基本信息
            String userInfo = HttpClientUtils.get(userInfoUrl);
            /*
              {
    "openid":"o3_SC5_eI--mIC9ikI2pvTuZhYnk",
    "nickname":"Kong",
    "sex":0,
    "language":"",
    "city":"",
    "province":"",
    "country":"",
    "headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/hAqkcbxzEJzic0WYl9pHDglAvYBI4iagLsSLXb2ialcxa3Au6UmwibSiadGMtbQia0oAzmzq26k2f1ES4q1HbS6aIYuA\/132",
    "privilege":[],
    "unionid":"oWgGz1OqVll-tTU4R_DM_zRp7Rjc"
                }
             */
            //將上面的json字符串轉(zhuǎn)換成map對(duì)象
            HashMap mapUserInfo = gson.fromJson(userInfo, HashMap.class);
            //掃碼人基礎(chǔ)信息
            String nickname = (String)mapUserInfo.get("nickname");
            String headImgurl=(String)mapUserInfo.get("headimgurl");
            String openId=(String)mapUserInfo.get("openid");

            //掃碼后自動(dòng)注冊(cè)(入庫)
            //先判斷是否已注冊(cè)
            boolean isExist = memberService.getUserOpenId(openId);
            if(!isExist){
                //入庫
                UcenterMember member = new UcenterMember();
                member.setNickname(nickname);
                member.setOpenid(openid);
                member.setAvatar(headImgurl);
                memberService.save(member);
            }
            UcenterMember ucenterMember = memberService.getUserByOpenId(openId);
            String token = JwtUtils.getJwtToken(ucenterMember.getId(), ucenterMember.getNickname());
            //因?yàn)槎丝谔?hào)不同存在跨域問題,cookie不能跨域,所以這里使用url重寫
            return "redirect:http://localhost:3000?token="+token;
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20010,"登錄失敗!");
        }
    }

總結(jié)

實(shí)現(xiàn)微信授權(quán)登錄就好比開寶箱,一共需要3把鑰匙,第一把鑰匙是appid(這個(gè)需要在微信開放平臺(tái) 完成注冊(cè)和認(rèn)證由平臺(tái)頒發(fā));

通過appid請(qǐng)求固定地址可以生成微信二維碼;用戶掃描二維碼授權(quán)后拿到第二把鑰匙code(隨機(jī)唯一值);

再通過code去請(qǐng)求固定服務(wù)器地址拿到第三把鑰匙o(hù)penid(用戶唯一標(biāo)識(shí))和accessToken(訪問憑證);

最后再通過openid和accessToken請(qǐng)求固定地址拿到微信用戶基本信息。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • IDEA?tomcat啟動(dòng)項(xiàng)目方式

    IDEA?tomcat啟動(dòng)項(xiàng)目方式

    這篇文章主要介紹了IDEA?tomcat啟動(dòng)項(xiàng)目方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • mybatis中insert返回值為1,但數(shù)據(jù)庫卻沒有數(shù)據(jù)

    mybatis中insert返回值為1,但數(shù)據(jù)庫卻沒有數(shù)據(jù)

    這篇文章主要介紹了mybatis中insert返回值為1,但數(shù)據(jù)庫卻沒有數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java中jstat命令的使用詳解

    Java中jstat命令的使用詳解

    jstat命令可以查看堆內(nèi)存各部分的使用量,以及加載類的數(shù)量,下面這篇文章主要給大家介紹了關(guān)于Java中jstat命令使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • Java內(nèi)存模型原子性原理及實(shí)例解析

    Java內(nèi)存模型原子性原理及實(shí)例解析

    這篇文章主要介紹了Java內(nèi)存模型原子性原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Minio環(huán)境部署過程及如何配置HTTPS域名

    Minio環(huán)境部署過程及如何配置HTTPS域名

    MinIO?是一個(gè)對(duì)象存儲(chǔ)系統(tǒng),數(shù)據(jù)需要存儲(chǔ)在宿主機(jī)上,容器的重啟不影響數(shù)據(jù),因此我們需要為?MinIO?創(chuàng)建一個(gè)掛載目錄,用于持久化存儲(chǔ)數(shù)據(jù),本文詳細(xì)介紹了如何部署MinIO,并通過配置反向代理和HTTPS來提升其安全性,感興趣的朋友一起看看吧
    2025-03-03
  • 探討Java驗(yàn)證碼制作(上篇)

    探討Java驗(yàn)證碼制作(上篇)

    很多朋友對(duì)驗(yàn)證碼并不陌生,無論是申請(qǐng)賬號(hào)還是某些情況下登錄時(shí)都會(huì)要求輸入驗(yàn)證碼。接下來通過本文給大家介紹java驗(yàn)證碼制作的方法,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • 基于Java實(shí)現(xiàn)OCR 文字識(shí)別的兩種方案

    基于Java實(shí)現(xiàn)OCR 文字識(shí)別的兩種方案

    OCR技術(shù)已廣泛應(yīng)用于圖文轉(zhuǎn)換、證件識(shí)別、票據(jù)處理等場(chǎng)景,作為 Java 開發(fā)者,如何快速實(shí)現(xiàn) OCR 功能?本文將介紹兩種常用方案,幫助你快速上手 Java OCR 開發(fā),需要的朋友可以參考下
    2025-12-12
  • Java 由淺入深帶你掌握?qǐng)D的遍歷

    Java 由淺入深帶你掌握?qǐng)D的遍歷

    圖的遍歷是指,從給定圖中任意指定的頂點(diǎn)(稱為初始點(diǎn))出發(fā),按照某種搜索方法沿著圖的邊訪問圖中的所有頂點(diǎn),使每個(gè)頂點(diǎn)僅被訪問一次,這個(gè)過程稱為圖的遍歷。遍歷過程中得到的頂點(diǎn)序列稱為圖遍歷序列
    2022-03-03
  • 淺談Java中復(fù)制數(shù)組的方式

    淺談Java中復(fù)制數(shù)組的方式

    這篇文章主要介紹了Java中復(fù)制數(shù)組的幾種方法,需要的朋友可以參考下。
    2017-08-08
  • 基于Spring AOP實(shí)現(xiàn)日志自動(dòng)打印功能

    基于Spring AOP實(shí)現(xiàn)日志自動(dòng)打印功能

    這篇文章主要介紹了基于Spring AOP實(shí)現(xiàn)日志自動(dòng)打印功能,文中通過代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2025-01-01

最新評(píng)論

陆丰市| 易门县| 元氏县| 青海省| 定襄县| 湘乡市| 环江| 西乌珠穆沁旗| 北票市| 炉霍县| 尚义县| 新巴尔虎左旗| 洛川县| 辽中县| 西乌珠穆沁旗| 五家渠市| 大渡口区| 三穗县| 白朗县| 若尔盖县| 永福县| 云南省| 曲阳县| 丰原市| 合阳县| 孟津县| 南安市| 景东| 阿拉尔市| 贡觉县| 永修县| 台东市| 桓台县| 健康| 叙永县| 嵊州市| 镇沅| 石狮市| 广元市| 永年县| 永春县|