public class Global {

	/**
	 * 当前对象实例
	 */
	private static Global global = new Global();
	
	/**
	 * 保存全局属性值
	 */
	private static Map<String, String> map = Maps.newHashMap();
	
	/**
	 * 属性文件加载对象
	 */
	private static PropertiesLoader loader = new PropertiesLoader("jeesite.properties");

	/**
	 * 显示/隐藏
	 */
	public static final String SHOW = "1";
	public static final String HIDE = "0";

	/**
	 * 是/否
	 */
	public static final String YES = "1";
	public static final String NO = "0";
	
	/**
	 * 对/错
	 */
	public static final String TRUE = "true";
	public static final String FALSE = "false";
	
	/**
	 * 男/女
	 */
	public static final String MALE = "0";
	public static final String FEMALE = "1";
	
	/**
	 * 上传文件基础虚拟路径
	 */
	public static final String USERFILES_BASE_URL = "/userfiles/";
	
	/**
	 * 获取当前对象实例
	 */
	public static Global getInstance() {
		return global;
	}
	
	/**
	 * 获取配置
	 * @see ${fns:getConfig('adminPath')}
	 */
	public static String getConfig(String key) {
		String value = map.get(key);
		if (value == null){
			value = loader.getProperty(key);
			map.put(key, value != null ? value : StringUtils.EMPTY);
		}
		return value;
	}
	
	/**
	 * 获取管理端根路径
	 */
	public static String getAdminPath() {
		return getConfig("adminPath");
	}
	
	/**
	 * 获取前端根路径
	 */
	public static String getFrontPath() {
		return getConfig("frontPath");
	}
	
	/**
	 * 获取URL后缀
	 */
	public static String getUrlSuffix() {
		return getConfig("urlSuffix");
	}
	
	/**
	 * 是否是演示模式，演示模式下不能修改用户、角色、密码、菜单、授权
	 */
	public static Boolean isDemoMode() {
		String dm = getConfig("demoMode");
		return "true".equals(dm) || "1".equals(dm);
	}
	
	/**
	 * 页面获取常量
	 * @see ${fns:getConst('YES')}
	 */
	public static Object getConst(String field) {
		try {
			return Global.class.getField(field).get(null);
		} catch (Exception e) {
			// 异常代表无配置，这里什么也不做
		}
		return null;
	}

	/**
	 * 获取上传文件的根目录
	 * @return
	 */
	public static String getUserfilesBaseDir() {
		String dir = getConfig("userfiles.basedir");
		if (StringUtils.isBlank(dir)){
			try {
				dir = ServletContextFactory.getServletContext().getRealPath("/");
			} catch (Exception e) {
				return "";
			}
		}
		if(!dir.endsWith("/")) {
			dir += "/";
		}
//		System.out.println("userfiles.basedir: " + dir);
		return dir;
	}
	
    /**
     * 获取工程路径
     * @return
     */
    public static String getProjectPath(){
    	// 如果配置了工程路径，则直接返回，否则自动获取。
		String projectPath = Global.getConfig("projectPath");
		if (StringUtils.isNotBlank(projectPath)){
			return projectPath;
		}
		try {
			File file = new DefaultResourceLoader().getResource("").getFile();
			if (file != null){
				while(true){
					File f = new File(file.getPath() + File.separator + "src" + File.separator + "main");
					if (f == null || f.exists()){
						break;
					}
					if (file.getParentFile() != null){
						file = file.getParentFile();
					}else{
						break;
					}
				}
				projectPath = file.toString();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return projectPath;
    }
	
} public class CTelsms extends DataEntity<CTelsms> {
	
	private static final long serialVersionUID = 1L;
	private String phone;		// phone
	private String type;		// 0:注册1:找回密码
	private String code;		// code
	private String userId;			// user_id
	
	public CTelsms() {
		super();
	}

	public CTelsms(String id){
		super(id);
	}

	@Length(min=0, max=15, message="phone长度必须介于 0 和 15 之间")
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}
	
	@Length(min=0, max=1, message="0:注册1:找回密码长度必须介于 0 和 1 之间")
	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	@Length(min=0, max=10, message="code长度必须介于 0 和 10 之间")
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}
	
} @Service
@Transactional(readOnly = true)
public class CTelsmsService extends CrudService<CTelsmsDao, CTelsms> {

	public CTelsms get(String id) {
		return super.get(id);
	}
	
	public List<CTelsms> findList(CTelsms cTelsms) {
		return super.findList(cTelsms);
	}
	
	public Page<CTelsms> findPage(Page<CTelsms> page, CTelsms cTelsms) {
		return super.findPage(page, cTelsms);
	}
	
	@Transactional(readOnly = false)
	public void save(CTelsms cTelsms) {
		super.save(cTelsms);
	}
	
	@Transactional(readOnly = false)
	public void delete(CTelsms cTelsms) {
		super.delete(cTelsms);
	}

	/**
	 * 校验手机验证码
	 * @param mobile 手机号
	 * @param code 验证码
	 * @return true 校验成功
	 */
	@Transactional(readOnly = false)
	public boolean validateCode(String mobile, String code) {
		if (StringUtils.isAnyBlank(mobile,code)) {
			return false;
		}
		CTelsms telsmsBean = new CTelsms();
		telsmsBean.setPhone(mobile);
		telsmsBean.setCode(code);
		telsmsBean.setDelFlag(CTelsms.DEL_FLAG_NORMAL);
		List<CTelsms> list = this.findList(telsmsBean);
		if (list == null || list.size() == 0) {
			return false;
		}
		this.delete(list.get(0));
		return true;
	}
	
	
} public class CUser extends DataEntity<CUser> {
	
	private static final long serialVersionUID = 1L;
	private String loginName;		// 登录名
	private String deviceType;      // 设备类型
	private String deviceId;		// 设备ID
	private String openId;		    // 第三方ID
	private String realName;		// 用户名
	private String nickName;		// 昵称
	private String imageUrl;		// 用户头像url
	private String sex;				// 默认男性
	private String phone;			// 手机号码
	private String password;		// 密码
	private String jf; 				// 积分
	private String status;			// 启用?
	private String userType;		// 用户分类
	
	public CUser() {
		super();
	}

	public CUser(String id){
		super(id);
	}

	public String getLoginName() {
		return loginName;
	}

	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}

	public String getDeviceType() {
		return deviceType;
	}

	public void setDeviceType(String deviceType) {
		this.deviceType = deviceType;
	}

	public String getDeviceId() {
		return deviceId;
	}

	public void setDeviceId(String deviceId) {
		this.deviceId = deviceId;
	}

	public String getOpenId() {
		return openId;
	}

	public void setOpenId(String openId) {
		this.openId = openId;
	}

	public String getRealName() {
		return realName;
	}

	public void setRealName(String realName) {
		this.realName = realName;
	}

	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getImageUrl() {
		return imageUrl;
	}

	public void setImageUrl(String imageUrl) {
		this.imageUrl = imageUrl;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getJf() {
		return jf;
	}

	public void setJf(String jf) {
		this.jf = jf;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getUserType() {
		return userType;
	}

	public void setUserType(String userType) {
		this.userType = userType;
	}

} @Service
@Transactional(readOnly = true)
public class CSessionService extends CrudService<CSessionDao, CSession> {

	public CSession get(String id) {
		return super.get(id);
	}
	
	public List<CSession> findList(CSession cSession) {
		return super.findList(cSession);
	}
	
	public Page<CSession> findPage(Page<CSession> page, CSession cSession) {
		return super.findPage(page, cSession);
	}
	
	@Transactional(readOnly = false)
	public void save(CSession cSession) {
		super.save(cSession);
	}
	
	@Transactional(readOnly = false)
	public void delete(CSession cSession) {
		super.delete(cSession);
	}
	
} @Service
@Transactional(readOnly = true)
public class CUserService extends CrudService<CUserDao, CUser> {
	
	@Autowired
	CSessionService sessionService;
	
	public CUser get(String id) {
		return super.get(new CUser(id));
	}
	
	public List<CUser> findList(CUser cUser) {
		return super.findList(cUser);
	}
	
	public Page<CUser> findPage(Page<CUser> page, CUser cUser) {
		return super.findPage(page, cUser);
	}
	
	@Transactional(readOnly = false)
	public void save(CUser cUser) {
		super.save(cUser);
	}
	
	@Transactional(readOnly = false)
	public void delete(CUser cUser) {
		super.delete(cUser);
	}
	
	/**
	 * 查询用户是否被冻结
	 * @param userId
	 * @return
	 */
	public boolean isLock(String userId){
		CUser user = this.get(userId);
		return Constants.USER_STATUS_LOCK.equals(user.getStatus());
	}
	
	// 用户登录
	@Transactional(readOnly = false)
	public String doLogin(UserDomain domain) throws BusinessException {
		CUser userBean = new CUser();
		userBean.setLoginName(domain.getUserName());
		userBean.setPassword(new Md5Hash(domain.getPassword()).toHex());
		List<CUser> userList = findList(userBean);
		if (userList == null || userList.size() == 0) {
			throw new BusinessException(Constants.ERRORCODE_INVALID_USERNAME_PASSWORD,"用户名或密码不正确");
		}
		if (userList.get(0).getStatus().equals(Constants.USER_STATUS_LOCK)) {
			throw new BusinessException(Constants.ERRORCODE_USER_LOCKED,"用户被冻结");
		}
		String currentSessionId = doSessioon(domain, userList.get(0).getId());
		// 创建Token
		String token = TokenUtils.encryptToken(new UserToken(userList.get(0).getId(), currentSessionId, userList.get(0).getUserType(), userList.get(0).getLoginName(), System.currentTimeMillis()));
		return token;
	}
	
	/**
	 * 创建Session
	 * @param domain
	 * @param userId
	 * @return
	 */
	@Transactional(readOnly = false)
	private String doSessioon(UserDomain domain, String userId){
		// 创建session
		String currentSessionId = IdGen.uuid();
		CSession sessionBean = new CSession();
		sessionBean.setUserId(userId);
		sessionBean.setId(currentSessionId);
		sessionBean.setIsNewRecord(true);
		sessionBean.setDeviceType(domain.getDeviceType());
		sessionBean.setLoginIp(domain.getRemoteIP());
		sessionBean.setLoginDate(new Date());
		sessionBean.setStatus(Constants.SESSION_STATUS_LOGIN);
		sessionService.save(sessionBean);
		// 同一种设备类型只允许一个用户登录
		sessionBean = new CSession();
		sessionBean.setUserId(userId);
		sessionBean.setDeviceType(domain.getDeviceType());
		sessionBean.setStatus(Constants.SESSION_STATUS_LOGIN);
		List<CSession> sessionList = sessionService.findList(sessionBean);
		if (sessionList.size() > 1) {
			for (int i = 0; i < sessionList.size(); i++) {
				CSession s = sessionList.get(i);
				if (currentSessionId.equals(s.getId())) {
					continue;
				}
				s.setStatus(Constants.SESSION_STATUS_KICKOUT);
				sessionService.save(s);
			}
		}
		return currentSessionId;
	}
	
	// 注册新用户（且登录）
	@Transactional(readOnly = false)
	public String registerUser(UserDomain domain) {
		CUser userBean = new CUser();
		userBean.setId(IdGen.uuid());
		userBean.setIsNewRecord(true);
		if (Constants.USER_TYPE_GUEST.equals(TokenUtils.getCurrentToken().getUserType())) {
			userBean.setId(TokenUtils.getCurrentToken().getUserId());
			userBean.setIsNewRecord(false);
		}
		userBean.setLoginName(domain.getUserName());
		userBean.setPassword(new Md5Hash(domain.getPassword()).toHex().toUpperCase());
		userBean.setDeviceType(domain.getDeviceType());
		userBean.setUserType(Constants.USER_TYPE_USER);
		userBean.setPhone(domain.getUserName());
		userBean.setNickName("会员");
		this.save(userBean);
		String sessionId = doSessioon(domain, userBean.getId());
		return TokenUtils.encryptToken(new UserToken(userBean.getId(), sessionId, userBean.getUserType(), userBean.getLoginName(), System.currentTimeMillis()));
	}
	
	/**
	 * 第三方登录
	 * @throws BusinessException 
	 */
	@Transactional(readOnly = false)
	public String thirdPartyLogin(UserDomain domain) throws BusinessException {
		String sessionId = "";
		CUser userBean = new CUser();
		userBean.setOpenId(domain.getThirdpartyId());
		userBean.setDelFlag(CUser.DEL_FLAG_NORMAL);
		List<CUser> userList = this.findList(userBean);
		//新帐号
		if (userList == null || userList.size() < 1) {
			if (Constants.USER_TYPE_GUEST.equals(TokenUtils.getCurrentToken().getUserType())) {
				userBean.setId(TokenUtils.getCurrentToken().getUserId());
				userBean.setIsNewRecord(false);
			}else{
				userBean.setId(IdGen.uuid());
				userBean.setIsNewRecord(true);
			}
			userBean.setUserType(Constants.USER_TYPE_THIRDPARTY);
			userBean.setDeviceType(domain.getDeviceType());
			userBean.setNickName("会员");
			this.save(userBean);
			sessionId = doSessioon(domain, userBean.getId());
			return TokenUtils.encryptToken(new UserToken(userBean.getId(), sessionId, userBean.getUserType(), System.currentTimeMillis()));
		}else{
		//老账号
			if (userList.get(0).getStatus().equals(Constants.USER_STATUS_LOCK)) {
				throw new BusinessException(Constants.ERRORCODE_USER_LOCKED,"用户被冻结");
			}
			sessionId = doSessioon(domain, userList.get(0).getId());
			return TokenUtils.encryptToken(new UserToken(userList.get(0).getId(), sessionId, userList.get(0).getUserType(), System.currentTimeMillis()));
		}
	}

	/**
	 * 生成匿名访客Token
	 * @return
	 */
	@Transactional(readOnly = false)
	public String getGuestToken() {
		CUser userBean = new CUser();
		userBean.setIsNewRecord(true);
		String userId = IdGen.uuid();
		userBean.setId(userId);
		userBean.setUserType(Constants.USER_TYPE_GUEST);
		userBean.setNickName("访客");
		this.save(userBean);
		return TokenUtils.encryptToken(new UserToken(userId, null, Constants.USER_TYPE_GUEST, null, null));
	}

	/**
	 * 退出
	 * @param domain
	 */
	@Transactional(readOnly = false)
	public void doLogout(UserDomain domain) {
		UserToken ut = TokenUtils.getCurrentToken();
		if (Constants.USER_TYPE_THIRDPARTY.equals(ut.getUserType()) || Constants.USER_TYPE_USER.equals(ut.getUserType())) {
			CSession sessionBean = new CSession();
			sessionBean = sessionService.get(ut.getSessionId());
			if (sessionBean != null) {
				sessionBean.setStatus(Constants.SESSION_STATUS_LOGOUT);
				sessionBean.setLogoutDate(new Date());
				sessionService.save(sessionBean);
			}
		}
	}
} public class ApiResponse {

	public static final String SUCCESS = "0";
	public static final String FAIL = "-1";

	private String code = FAIL;
	private String message = null;
	private Object data = null;

	private ApiResponse(){}

	private ApiResponse(String code, String message, Object data) {
		this.code = code;
		this.message = message;
		this.data = data;
	}

	private ApiResponse(String code, String message) {
		this(code, message, null);
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public static ApiResponse failMessage(String message) {
		return new ApiResponse(FAIL, message);
	}

	public static ApiResponse failMessage(String code, String message) {
		return new ApiResponse(code, message);
	}

	public static ApiResponse successMessage(String message, Object data) {
		return new ApiResponse(SUCCESS, message, data);
	}
} public abstract class BaseController {

	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	/**
	 * 参数绑定异常
	 */
	@ExceptionHandler(value=Exception.class)
	@ResponseBody
    public ApiResponse bindException(Exception e) {
		logger.error(Exceptions.getStackTraceAsString(e));
		return ApiResponse.failMessage("系统错误");
    }
	
	/**
	 * 初始化数据绑定
	 * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
	 * 2. 将字段中Date类型转换为String类型
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
		binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
			}
			@Override
			public String getAsText() {
				Object value = getValue();
				return value != null ? value.toString() : "";
			}
		});
	}
} public class Constants {
	
	//用户类型
	public static final String USER_TYPE_GUEST = "0";
	public static final String USER_TYPE_USER = "1";
	public static final String USER_TYPE_THIRDPARTY = "2";
	
	//用户状态
	public static final String USER_STATUS_NORMAL = "0";
	public static final String USER_STATUS_LOCK = "1";
	
	//会话状态
	public static final String SESSION_STATUS_LOGIN = "0";
	public static final String SESSION_STATUS_LOGOUT = "1";
	public static final String SESSION_STATUS_KICKOUT = "2";
	public static final String SESSION_STATUS_EXPIRE = "3";
	
	//设备类型
	public static final String DEVICE_TYPE_IPHONE = "0";
	public static final String DEVICE_TYPE_IPAD = "1";
	public static final String DEVICE_TYPE_IWATCH = "2";
	public static final String DEVICE_TYPE_ANDROID = "5";
	public static final String DEVICE_TYPE_ANDROID_PAD = "6";
	public static final String DEVICE_TYPE_ANDROID_WATCH = "7";
	
	//错误码
	public static final String ERRORCODE_INVALID_PARAM = "1000";
	public static final String ERRORCODE_AUTHENTICODE_TOO_FREQUENTLY = "1001";
	public static final String ERRORCODE_INVALID_PHONE_NUM = "1002";
	public static final String ERRORCODE_USER_EXIST = "1003";
	public static final String ERRORCODE_SIMPLE_PASSWORD = "1004";
	public static final String ERRORCODE_INVALID_AUTHENTICODE = "1005";
	public static final String ERRORCODE_INVALID_DEVICE_TYPE = "1006";
	public static final String ERRORCODE_INVALID_USERNAME_PASSWORD = "1007";
	public static final String ERRORCODE_USER_LOCKED = "1008";
	public static final String ERRORCODE_INVALID_TOKEN = "1009";
	public static final String ERRORCODE_NOT_LOGIN = "1010";
	public static final String ERRORCODE_SESSION_KICKOUT = "1011";
	public static final String ERRORCODE_SESSION_LOGOUT = "1012";
	public static final String ERRORCODE_SESSION_EXPIRE = "1013";
	
} public class UserToken implements Serializable{

	private static final long serialVersionUID = -2910636802113452789L;
	private String userId;
	private String sessionId;
	private String userType;
	private String loginName;
	private Long loginTime;
	
	public UserToken(String userId,String sessionId,String userType,String loginName,Long loginTime) {
		this.userId = userId;
		this.sessionId = sessionId;
		this.userType = userType;
		this.loginName = loginName;
		this.loginTime = loginTime;
	}
	
	public UserToken(String userId,String userType) {
		this(userId,null,userType,null,null);
	}
	
	public UserToken(String userId,String sessionId,String userType,Long loginTime) {
		this(userId,sessionId,userType,null,loginTime);
	}

	public String getUserId() {
		return userId;
	}

	public String getSessionId() {
		return sessionId;
	}

	public String getUserType() {
		return userType;
	}

	public String getLoginName() {
		return loginName;
	}

	public Long getLoginTime() {
		return loginTime;
	}
} public class BusinessException extends Exception {

	private static final long serialVersionUID = 8386945553265545493L;
	
	private String code;

	public BusinessException() {
		super();
	}

	public BusinessException(String code, String message) {
		super(message);
		this.code = code;
	}

	public BusinessException(String code, String message, Throwable cause) {
		super(message, cause);
		this.code = code;
	}

	public String getCode() {
		return code;
	}
} public class TelUtil {
	// 验证码发送地址
	private static final String SMSURLSTR = "http://sdk.entinfo.cn:8061/webservice.asmx/mdsmssend";
	private static final String SN = "";
	private static final String SMSPWD = "";
	public static final String TELNUM = "139,138,137,136,135,134,147,188,187,184,183,182,178,159,158,157,152,151,150,186,185,176,145,156,155,132,131,130,189,181,180,177,153,133,189,133";
	/**
	 * @param mobilePhone
	 * @param code
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static boolean sendSMS(String mobilePhone, String code) {
		try {
			String content = ",为您的注册码，请您在一分钟内完成注册。如非本人操作，请忽略。【大手小手动起来】";
			String contentAuthCode = String.valueOf(code);
			String contentResult = java.net.URLEncoder.encode(contentAuthCode + content, "utf-8");
			String param = "sn=" + SN + "&pwd=" + SMSPWD + "&mobile=" + mobilePhone
					+ "&content=" + contentResult + "&ext=1&stime=&rrid=&msgfmt=";
			HttpUtils.sendGet(SMSURLSTR, param);
			return true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return false;
		}
	}

	public static void main(String[] args) throws UnsupportedEncodingException {
//		BigDecimal a1 = new BigDecimal("8817010393021010");
//		BigDecimal a2 = new BigDecimal("1"); 
		System.out.println(TelUtil.sendSMS("18501364095","1314"));
//		System.out.println(TelAuthUtil.sendSMS("18611140788",1314));
//		String code = (int)(Math.random()*10)+""+(int)(Math.random()*10)+(int)(Math.random()*10)+(int)(Math.random()*10);
//		System.out.println(code);
	}
} public class TokenUtils {
	
	private static final Logger logger = LoggerFactory.getLogger(TokenUtils.class);
	
	private static final String ENCRYPT_KEY = "59FF4BEDF5155319CE6F39815653C60A";
	private static final String SEPARATE = ":";
	private static final String SESSION_KEY = "CUSERTOKEN";

	/**
	 * 加密Token
	 * ${userId}:${sessionId}:${userType}:${loginName}:${loginTime}
	 * 
	 */
	public static String encryptToken(UserToken ut) {
		if (StringUtils.isEmpty(ut.getUserId()) || StringUtils.isEmpty(ut.getUserType())) {
			logger.error("userId:"+ut.getUserId()+",userType:"+ut.getUserType());
			return null;
		}
		StringBuilder tokenStr = new StringBuilder();
		tokenStr.append(ut.getUserId());
		tokenStr.append(SEPARATE);
		tokenStr.append(ut.getSessionId() == null ? "":ut.getSessionId());
		tokenStr.append(SEPARATE);
		tokenStr.append(ut.getUserType());
		tokenStr.append(SEPARATE);
		tokenStr.append(ut.getLoginName() == null ? "":ut.getLoginName());
		tokenStr.append(SEPARATE);
		tokenStr.append(ut.getLoginTime() == null ? "":ut.getLoginTime());
		logger.info("original token string :"+tokenStr);
		return Cryptos.aesEncrypt(tokenStr.toString(), ENCRYPT_KEY);
	}
	
	/**
	 * 解密Token
	 */
	public static UserToken decryptToken(String encrypt) {
		if (encrypt == null) {
			return null;
		}
		String[] tmpArray = null;
		try {
			String tokenStr = Cryptos.aesDecrypt(encrypt, ENCRYPT_KEY);
			tmpArray = tokenStr.split(SEPARATE);
		} catch (Exception e) {
			return null;
		}
		String userType = tmpArray[2];
		if (Constants.USER_TYPE_GUEST.equals(userType)) {
			return new UserToken(tmpArray[0], tmpArray[2]);
		}
		if (Constants.USER_TYPE_THIRDPARTY.equals(userType)) {
			return new UserToken(tmpArray[0], tmpArray[1], tmpArray[2], Long.parseLong(tmpArray[4]));
		}
		if (Constants.USER_TYPE_USER.equals(userType)) {
			return new UserToken(tmpArray[0], tmpArray[1], tmpArray[2], tmpArray[3], Long.parseLong(tmpArray[4]));
		}
		return null;
	}
	
	/**
	 * 获取Token
	 */
	public static UserToken getCurrentToken(){
		Session session = TokenUtils.getSession();
		return (UserToken)session.getAttribute(SESSION_KEY);
	}
	
	/**
	 * 保存Token
	 */
	public static void saveTokenToSession(UserToken token){
		Session session = TokenUtils.getSession();
		session.setAttribute(SESSION_KEY, token);
	}
	
	/**
	 * 获取Shiro管理的Session
	 * @return
	 */
	private static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			return subject.getSession(true);
		}catch (InvalidSessionException e){
		}
		return null;
	}
} public class UserDomain extends BaseDomain{
	private String userName;		//用户名（手机号）
	private String password;		//密码
	private String code;			//验证码
	private String deviceType;		//设备类型
	private String thirdpartyId;	//第三方登录ID
	private String sign;			//签名字符串
	
	public String getDeviceType() {
		return deviceType;
	}
	public void setDeviceType(String deviceType) {
		this.deviceType = deviceType;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public String getThirdpartyId() {
		return thirdpartyId;
	}
	public void setThirdpartyId(String thirdpartyId) {
		this.thirdpartyId = thirdpartyId;
	}
	public String getSign() {
		return sign;
	}
	public void setSign(String sign) {
		this.sign = sign;
	}
}
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.security.Cryptos;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.utils.Exceptions;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.zlwh.hands.admin.modules.basis.entity.CTelsms;
import com.zlwh.hands.admin.modules.basis.service.CTelsmsService;
import com.zlwh.hands.admin.modules.user.entity.CUser;
import com.zlwh.hands.admin.modules.user.service.CSessionService;
import com.zlwh.hands.admin.modules.user.service.CUserService;
import com.zlwh.hands.api.common.ApiResponse;
import com.zlwh.hands.api.common.BaseController;
import com.zlwh.hands.api.common.Constants;
import com.zlwh.hands.api.common.UserToken;
import com.zlwh.hands.api.common.annotation.RequiredLogin;
import com.zlwh.hands.api.common.exception.BusinessException;
import com.zlwh.hands.api.common.utils.TelUtil;
import com.zlwh.hands.api.common.utils.TokenUtils;
import com.zlwh.hands.api.domain.UserDomain;
package com.zlwh.hands.api;





@Controller
@RequestMapping(value = "api/1.0/user/")
public class CLoginController extends BaseController{
	
	@Autowired
	CUserService userService;
	@Autowired
	CTelsmsService cTelsmsService;
	@Autowired
	CSessionService sessionService;
	
	// 验证码超时时间
	private static final Long EXPIRE = 60 * 1000L;
	
	
	/**
	 * 获取UserToken
	 * 请求URL示例：http://localhost:8080/hands/api/1.0/user/getToken?sign=xxxxxxxxxxxxxxxxxxxxx
	 * sign = AES(PARAM_KEY + ":" + DEVICE_ID + ":" + TIMESTAMP)
	 * 防止该接口被恶意调用数据库频繁插入C_USER表
	 */
	@RequestMapping(value="getToken")
	@ResponseBody
	public ApiResponse getToken(UserDomain domain){