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;
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;
/**
* 第三方登录绑定账号
*/
@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/>
密 码:
<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> <!--解绑-->