springmvc+shiro 微信登录

tomcat端口号改为80
放行微信需要的路径(anno)

数据库
employee

CREATE TABLE `employee` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `headImage` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `department_id` bigint(20) DEFAULT NULL,
  `wechat_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK4AFD4ACE851EFECF` (`department_id`),
  KEY `FK_ID` (`wechat_id`),
  CONSTRAINT `FK4AFD4ACE851EFECF` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`),
  CONSTRAINT `FK_ID` FOREIGN KEY (`wechat_id`) REFERENCES `wechat` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=329 DEFAULT CHARSET=utf8;


wechat

CREATE TABLE `wechat` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `openid` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;


DAO层
Employee

 @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "wechat_id")
    private Wechat wechat;

Wechat

/**
 * 第三方登录绑定账号
 */
@Entity
@Table(name = "wechat")
public class Wechat extends BaseDomain{
    private String openid;

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }


    @Override
    public String toString() {
        return "Wechat{" +
                "openid='" + openid + '\'' +
                ", id=" + id +
                '}';
    }
}

Repository层
EmployeeRepository

//根据opoenId去数据库获取user对象
 @Query("select e from  Employee e join e.wechat w where w.openid=?1")
 Employee findByOpenid(String openId);

WechatRepository


public interface WechatRepository extends BaseRepository<Wechat,Long>{
/*根据openid查询是否存在*/
@Query("select w from Wechat w where w.openid=?1")
    Wechat findOpenId(String openId);
}

Service层
IWechatService


public interface IWechatService extends IBaseService<Wechat,Long>{
/*查询是否存在openid*/
    Wechat findOpenId(String openId);
}

WechatServiceImpl


@Service
public class WechatServiceImpl extends BaseServiceImpl<Wechat,Long> implements IWechatService {
@Autowired
private WechatRepository wechatRepository;
    @Override
    public Wechat findOpenId(String openId) {
        return wechatRepository.findOpenId(openId);
    }
}

Controller层
WeChatController

package cn.itsource.aisell.web.controller;

import cn.itsource.aisell.domain.Employee;
import cn.itsource.aisell.domain.Wechat;
import cn.itsource.aisell.realm.EasyTypeToken;
import cn.itsource.aisell.service.IEmployeeService;
import cn.itsource.aisell.service.IWechatService;
import cn.itsource.aisell.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/wechat")
public class WeChatController {
    @Autowired
    private IEmployeeService employeeService;
    @Autowired
    private IWechatService wechatService;
    @RequestMapping("/callback")
        public String callback (Model model,String code, String state){
            //这里可以判断state是否改变判断此次请求是否安全
            //得到code换取token的地址

        String getTokenUrl = WxConstants.ACCESS_TOKEN.replace("APPID", WxConstants.APPID).replace("SECRET", WxConstants.APPSECRET).replace("CODE", code);

         //得到地址后通过工具类得到token
            String tokenResult = HttpClientUtil.doGet(getTokenUrl);
            System.out.println(tokenResult);
            //得到的token是json格式,将他转成map,得到换取用户资源的openid和access_token
            Map<String, String> tokenResultMap = JSON.parseObject(tokenResult, Map.class);
            //拿到token之后,换取用户资源
            String tokenString = tokenResultMap.get("access_token");
            String openId = tokenResultMap.get("openid");
            String userInfoUrl = WxConstants.USER_INFOURL.replace("ACCESS_TOKEN", tokenString).replace("OPENID", openId);
        Wechat openId1 = wechatService.findOpenId(openId);
        if(openId1==null){
            Wechat wechat = new Wechat();
            wechat.setOpenid(openId);
            wechatService.save(wechat);
        }
            //拿到了用户的基本信息
            String userResultStr = HttpClientUtil.doGet(userInfoUrl);
            System.out.println(userResultStr);
           //根据opoenId去数据库获取user对象
            Employee employee = employeeService.findByOpenid(openId);
            //如果user不为空 ,代码里面直接调用shiro的登录 -> 直接跳转主页
            if (employee != null) {
                String username = employee.getUsername();
                //这里用的就是我覆写的,并且通过自定义的拦截器,跳过密码的验证
                EasyTypeToken token = new EasyTypeToken(username);
                Subject subject = SecurityUtils.getSubject();
                subject.login(token);
               //从session中拿到用户对象
                UserContext.setUser(employee);
                model.addAttribute("unbind", "解绑");
                return "/index";

            }else{


                model.addAttribute("openId", openId);
                return "/bindusers";
            }
                //如果user为空,说明这个openid没有绑定过,那么久要跳转到绑定页面


            //绑定页面显示两种情况 : 绑定已有账号 ; 绑定新注册账号 ,把openId传入到页面
            //如果提交的是已有账号绑定 用户名 ,密码 ,openId
            //带着用户名和密码去数据库中查询 ,如果查到了User  ,就修改User.openId 设置进去 ,update.user
            //如果是提交注册 :用户名 ,密码 ,验证码 ,手机号  , openId
            //先做注册操作 insert.user  ,把openId和user信息一并保存

    }

    @RequestMapping("/binds")//绑定
    public AjaxResult findByUsername(String username,String password,String openId){
        String md5 = Md5Util.createMD5(password);

        Employee byUsername = employeeService.findByUserandPassword(username,md5);
        if(byUsername!=null){
            Wechat openId1 = wechatService.findOpenId(openId);
           /* Long openIDid = openId1.getId();*/
            byUsername.setWechat(openId1);
            employeeService.save(byUsername);
            return new AjaxResult();
        }
        return new AjaxResult(false,"亲,此账号不存在,绑定失败!");

    }

    @RequestMapping("/unbinds")//解绑
    public String findBybind(String username){
        Employee byUsername = employeeService.findByUsername(username);
        if(byUsername.getWechat().getId()!=null){
            byUsername.setWechat(null);
            employeeService.save(byUsername);
            return "redirect:http://bugtracker.itsource.cn/login.jsp";
        }
        return null;

    }

}

Realm层
EasyTypeToken

import cn.itsource.aisell.util.LoginType;
import org.apache.shiro.authc.UsernamePasswordToken;

public class EasyTypeToken extends UsernamePasswordToken{
    //这随便写的吧应该都可以
    private static final long serialVersionUID = -2564928913725078138L;
    private LoginType type;//表示当前登录的类型
    public EasyTypeToken() {
        super();
    }
    public EasyTypeToken(String username, String password, LoginType type, boolean rememberMe,  String host) {
        super(username, password, rememberMe,  host);
        this.type = type;
    }
    /**免密登录*/
    public EasyTypeToken(String username) {
        super(username, "", false, null);
        this.type = LoginType.NOPASSWD;
    }
    /**账号密码登录*/
    public EasyTypeToken(String username, String password) {
        super(username, password, false, null);
        this.type = LoginType.PASSWORD;
    }
    public LoginType getType() {
        return type;
    }
    public void setType(LoginType type) {
        this.type = type;
    }
}

Util层
LoginType

public enum LoginType {
    PASSWORD("password"), // 密码登录
    NOPASSWD("nopassword"); // 免密登录
    private String code;// 状态值
    private LoginType(String code) {
        this.code = code;
    }
    public String getCode () {
        return code;
    }
}

WxConstants

/*微信登录常量封装*/
public class WxConstants {
    public final static String APPID = ;
    //用户授权后微信的回调域名
    public final static String CALLBACK="http://bugtracker.itsource.cn";
    public final static String SCOPE = "snsapi_login";
    public final static String APPSECRET = "4a5d5615f93f24bdba2ba8534642dbb6";
    //微信上获取code的地址
    public final static String CODEURL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
    //微信上获取at的地址
    public final static String ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    //微信上获取用户信息的地址
    public final static String USER_INFOURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
}

HttpClientUtil

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
/*微信登录工具类的封装*/
public class HttpClientUtil {
    // http://bugtracker.itsource.cn/wechat/callback?code=222&state=99
    // http://bugtracker.itsource.cn/wechat/callback    code=222&state=99
    public  static String doGet(String uri) {
        //1:创建一个HttpClient的实例
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //2:创建一个get请求实例
        HttpGet httpGet = new HttpGet(uri);
        //请求的响应:
        CloseableHttpResponse response1 = null;
        try {
            //3:使用HttpClient的实例执行get请求
            response1 = httpclient.execute(httpGet);
            //http请求的状态:404 500 200
            System.out.println(response1.getStatusLine());
            int statusCode = response1.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("------------------");
                //请求成功:
                HttpEntity entity1 = response1.getEntity();
                String result = EntityUtils.toString(entity1, "utf-8");
                System.out.println(result);
                return result;
            } else {
                System.out.println("请求失败:自己做自己的业务逻辑");

                //请求失败:自己做自己的业务逻辑
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;

    }
}

wxlogin.jsp 拉起微信登录二维码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>智销系统</title>
    <script type="text/javascript" src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<style type="text/css">
                          body{
                              background: url("/static/image/a.jpg");
                          }
    /*设置二维码高宽 二维码所占位置就是页面所显示区域*/
    iframe{
        width: 100%;
        height: 100%;
    }
</style>
</head>
<body>
<div id="login_container"></div>
<script type="text/javascript">
    var obj = new WxLogin({
        self_redirect:true,
        id:"login_container",
        appid: ,
        scope: "snsapi_login",
        redirect_uri: "http://bugtracker.itsource.cn/wechat/callback",
        state: "departure",
        style: "black",
        href: ""
    });
</script>
</body>
</html>

binduser.jsp 绑定用户

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>

</head>
<body>
<div align="center" style="margin-top: 100px;">

    <form   method="post" action="/wechat/binds">
                <input type="hidden" name="openId" value="${openId}">
                   用户名:

                   <input name="username" type="text" />
        <br/>
        <br/>


                    密&emsp;码:

                    <input name="password" type="password" />
        <br/>
        <br/>

               <button type="submit" value="提交" style="width: 30px;height: 30px"/>

        </form>

</div>
</body>
</html>

login.jsp

<a href="/wechat/unbinds?username=<shiro:principal property='username'/>"> ${unbind}</a>   <!--解绑-->

发布了6 篇原创文章 · 获赞 1 · 访问量 201

猜你喜欢

转载自blog.csdn.net/qq_41972951/article/details/103741509
今日推荐