微信点餐之后台扫码登录(11)
微信开放平台:https://open.weixin.qq.com/  扫描登录不支持个人账号
最终的微信登录事件的地址为:
http://applenst.natapp4.cc/sell/wechat/qrAuthorize?returnUrl=applenst.natapp4.cc/sell/seller/login
不走登录授权的测试地址为
http://applenst.natapp4.cc/sell/seller/login?openid=123qwe
新增卖家账号
创建javabean
package com.imooc.vo.admin;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
 * @author: menghaibin
 * @create: 2020-02-26 15:24
 * @description: 卖家信息
 **/
Data
Entity
public class SellerInfo {
    @Id
    @Column(name = "seller_id")
    private String sellerId;
    @Column(name = "username")
    private String username;
    @Column(name = "password")
    private String password;
    @Column(name = "openid")
    private String openid;
}
创建dao层接口
com\imooc\dao\SellerInfoDao.java
package com.imooc.dao;
import com.imooc.vo.admin.SellerInfo;
import org.springframework.data.jpa.repository.JpaRepository;
/**
 * Created by Administrator on 2020/2/26.
 */
public interface SellerInfoDao extends JpaRepository<SellerInfo,String>{
    public SellerInfo findByOpenid(String openid);
    public SellerInfo save(SellerInfo sellerInfo);
}
创建测试类
package com.imooc.dao;
import com.imooc.utils.JsonUtil;
import com.imooc.vo.admin.SellerInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
 * Created by Administrator on 2020/2/26.
 */
RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
public class SellerInfoDaoTest {
    @Autowired
    SellerInfoDao sellerInfoDao;
    @Test
    public void findByOpenid() throws Exception {
        SellerInfo sellerInfo = sellerInfoDao.findByOpenid("123qwe");
        log.info(JsonUtil.toJson(sellerInfo));
    }
    @Test
    public void save() throws Exception {
        SellerInfo sellerInfo = new SellerInfo();
        sellerInfo.setSellerId("123456");
        sellerInfo.setUsername("admin");
        sellerInfo.setPassword("admin");
        sellerInfo.setOpenid("123qwe");
        sellerInfoDao.save(sellerInfo);
    }
}
卖家扫码(获取到openid)
创建service层接口
com\imooc\service\SellerService.java
package com.imooc.service;
import com.imooc.vo.admin.SellerInfo;
public interface SellerService {
    /*通过openid查询卖家端信息*/
    public SellerInfo findSellerInfoByOpenid(String openid);
}
创建service层接口的实现类
com\imooc\service\imp\SellerServiceImp.java
package com.imooc.service.imp;
import com.imooc.dao.SellerInfoDao;
import com.imooc.service.SellerService;
import com.imooc.vo.admin.SellerInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @author: menghaibin
 * @create: 2020-02-26 15:39
 * @description: 卖家端登录
 **/
@Service
public class SellerServiceImp implements SellerService{
    @Autowired
    private SellerInfoDao sellerInfoDao;
    @Override
    public SellerInfo findSellerInfoByOpenid(String openid) {
        return sellerInfoDao.findByOpenid(openid);
    }
}
在application.yml文件中追加appid以及Secret
 #开发平台接入的公众号appid
 openAppId: wxf1687xxxxxxxxxxb
 #开发平台接入的公众号Secret
 openAppSecret: b65d46d51xxxxxxxxxxxxxxxx6ff886d71

在WechatAccountConfig.java文件中追加appid以及Secret属性
/*开放平台微信登录appid*/
private String openAppId;
/*开放平台微信登录app Secret*/
private String openAppSecret;
创建微信登录配置类
com\imooc\config\WeChatOpenConfig.java
package com.imooc.config;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
 * @author: menghaibin
 * @create: 2020-02-26 20:14
 * @description: 微信登录配置
 **/
@Component
public class WeChatOpenConfig {
    @Autowired
    private WechatAccountConfig accountConfig;
    @Bean
    public WxMpService wxOpenService(){
        WxMpService wxOpenService = new WxMpServiceImpl();
        wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage());
        return wxOpenService;
    }
    @Bean
    public WxMpConfigStorage wxOpenConfigStorage(){
        WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
        wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId());
        wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret());
        return wxMpInMemoryConfigStorage;
    }
}
controller实现
在WechatController.java类中追加微信登录qrAuthorize和qrUserInfo的实现,获取openid
/*微信登录*/
@GetMapping("qrAuthorize")
 public String qrAuthorize(@RequestParam("returnUrl") String returnUrl){
      /*url:授权成功后要跳转的路径*/
     String url = accountConfig.getDomainUrl() + "/sell/wechat/qrUserInfo";
     String redirectUrl = wxMpService.buildQrConnectUrl(url,WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN,URLEncoder.encode(returnUrl));
     log.info(redirectUrl);
      /*进行跳转*/
     return "redirect:"+redirectUrl;
 }
/*微信登录回调方法*/
@GetMapping("/qrUserInfo")
public String qrUserInfo(@RequestParam("code") String code,
                         @RequestParam("state") String returnUrl){
    /*code:授权成功后会返回一个code
    * state:授权成功后的原始参数*/
    WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
    try{
        wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
    }catch (WxErrorException e){
        log.error("微信授权失败");
    }
    /*得到openid*/
    String openId = wxMpOAuth2AccessToken.getOpenId();
    /*跳转到系统*/
    return "redirect:"+ returnUrl + "?openid="+openId;
}
卖家登录(获取到openid之后)
通过微信登录获取到用户的openid,通过查询数据库是否存在,如果不存在 则跳到错误页,如果存在,则设置一个token到redis 同时把token设置到cookie
1:在application.yml中配置reids链接信息
  redis:
    host: 192.168.1.106
    port: 6379

1:创建微信登录controller
com\imooc\controller\SellerUserController.java
package com.imooc.controller;
import com.imooc.config.WechatAccountConfig;
import com.imooc.exception.SellException;
import com.imooc.service.SellerService;
import com.imooc.utils.CookieUtil;
import com.imooc.vo.admin.SellerInfo;
import com.imooc.vo.enums.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * @author: menghaibin
 * @create: 2020-02-26 20:55
 * @description: 卖家后台登录 登出
 **/
@Controller
@RequestMapping("/seller")
@Slf4j
public class SellerUserController {
    @Autowired
    private SellerService sellerService;
    /*注解:redis 工具类*/
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private WechatAccountConfig accountConfig;
}
2:在刚才创建的SellerUserController中实现login方法
@GetMapping("/login")
public ModelAndView login(@RequestParam("openid") String openid,
                  HttpServletResponse response,
                  Map<String,Object> map){
    //1:数据库查询openid是否存在
    SellerInfo sellerInfo = sellerService.findSellerInfoByOpenid(openid);
    if(sellerInfo == null){
        throw new SellException(ResultEnum.LOGIN_FAIL);
    }
    //2:设置token至redis
    String token = UUID.randomUUID().toString();
    Integer expire = 7200;//过期时间 2小时
    /*参数1:key 格式化 以token_开头
    * 参数2:value
    * 参数3:过期时间
    * 参数4:过期时间的单位
    * */
    //把openid作为value存入reids
    redisTemplate.opsForValue().set(String.format("token_%s",token),openid,expire,TimeUnit.SECONDS);
    log.info(String.format("token_%s",token));
    //3:设置token至cookie 访问成功后 通过检查可以看到前端有了cookie
    CookieUtil.setCookie(response,"token",token,expire);
    log.info("成功");
    //跳转绝对地址
    /*思路:
    * 先设置token到redis key=(格式化)token_we23332234434 value=opeind_12345664
    * 在设置token到cookie 格式为token:we23332234434
    * 验证的时候通过拿到cookie的token值we23332234434去redis获取key([格式化]token_we23332234434)的值opeind_12345664存在不存在
    * */
    return new ModelAndView("redirect:"+accountConfig.getDomainUrl()+"/sell/seller/order/list");
}
卖家注销
在SellerUserController中实现logout方法
@GetMapping("/logout")
public ModelAndView logout(HttpServletRequest request,HttpServletResponse response,
                    Map<String,Object> map){
    //从cookie查询
    Cookie cookie = CookieUtil.getCookie(request,"token");
    if(cookie != null){
        //清除reids
        redisTemplate.opsForValue().getOperations().delete(String.format("token_%s",cookie.getValue()));
        //清除cookie
        CookieUtil.setCookie(response,"token",null,0);
    }
    map.put("msg",ResultEnum.LOGOUT_SUCCESS.getMsg());
     /*按实际业务跳转*/
    map.put("url","/sell/seller/order/list");
    return new ModelAndView("common/success",map);
}
请求拦截验证
面向切面技术:取到cookie 在根据cookie得到reids的value 如果存在则不拦截
1:定义一个exception类
com\imooc\exception\SellerAuthorizeException.java
package com.imooc.exception;
/**
 * @author: menghaibin
 * @create: 2020-02-27 11:34
 * @description: 登录校验的异常类 使用者为SellerAuthorizeAspect
 **/
public class SellerAuthorizeException extends RuntimeException{
}
2:定义一个切面
com\imooc\aspect\SellerAuthorizeAspect.java
package com.imooc.aspect;
import com.imooc.exception.SellerAuthorizeException;
import com.imooc.utils.CookieUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
 * @author: menghaibin
 * @create: 2020-02-27 11:21
 * @description: 切面 用于token验证
 **/
@Component
@Aspect
@Slf4j
public class SellerAuthorizeAspect {
    @Autowired
    private StringRedisTemplate redisTemplate;
    /*定义切入点
    * 拦截contorller下的seller开头的类的所有方法 但排除SellerUserController
    * */
    @Pointcut("execution(public * com.imooc.controller.Seller*.*(..))" +
    "&& !execution(public * com.imooc.controller.SellerUserController.*(..))")
    public void verify(){};
    @Before("verify()")
    public void doVerify(){
        /*获取HttpServletRequest*/
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        /*查询cookie*/
        Cookie cookie = CookieUtil.getCookie(request,"token");
        if(cookie == null){
            log.warn("[登录校验] cookie中查询不到token");
            throw new SellerAuthorizeException();
        }
        /*查询redis*/
        String redisValue = redisTemplate.opsForValue().get(String.format("token_%s",cookie.getValue()));
        log.info(redisValue);
        if(StringUtils.isEmpty(redisValue)){
            log.warn("[登录校验] redis中查询不到token");
            throw new SellerAuthorizeException();
        }
    }
}
3:定义一个捕获异常的handler
com\imooc\handler\SellerExceptionHandler.java
package com.imooc.handler;
import com.imooc.config.WechatAccountConfig;
import com.imooc.exception.SellException;
import com.imooc.exception.SellerAuthorizeException;
import com.imooc.vo.front.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
/**
 * @author: menghaibin
 * @create: 2020-02-27 11:51
 * @description: 登录校验异常捕获
 **/
@ControllerAdvice
public class SellerExceptionHandler {
    @Autowired
    private WechatAccountConfig accountConfig;
    //拦截登录异常
    @ExceptionHandler(value = SellerAuthorizeException.class)
    public ModelAndView handlerAuthorizeException(){
        /*跳转到微信登录地址 http://applenst.natapp4.cc/sell/wechat/qrAuthorize?returnUrl=applenst.natapp4.cc/sell/seller/login*/
        return  new ModelAndView("redirect:"
        .concat(accountConfig.getDomainUrl())
        .concat("/sell/wechat/qrAuthorize")
        .concat("?returnUrl=")
        .concat(accountConfig.getDomainUrl())
        .concat("/sell/seller/login"));
    }
    /*拦截常规异常*/
    @ExceptionHandler(value = SellException.class)
    @ResponseBody
    public ResultVo handlerSellerException(SellException e){
        ResultVo resultVo = new ResultVo();
        resultVo.setCode(e.getCode());
        resultVo.setMsg(e.getMessage());
        return resultVo;
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号