Pārlūkot izejas kodu

成都理工大学CAS

xiaof 2 gadi atpakaļ
vecāks
revīzija
2217563ab0

+ 7 - 0
cdut-exchange/pom.xml

@@ -6,6 +6,7 @@
     <artifactId>cdut-exchange</artifactId>
     <version>1.0.0</version>
     <packaging>jar</packaging>
+    <description>成都理工大学单点登录</description>
 
     <parent>
         <groupId>com.qmth.teachcloud.exchange.service</groupId>
@@ -23,6 +24,12 @@
             <artifactId>spring-boot-starter-web</artifactId>
             <version>${spring-boot.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+            <version>9.0.64</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 69 - 99
cdut-exchange/src/main/java/com/qmth/cdut/api/OpenApiController.java

@@ -1,20 +1,19 @@
 package com.qmth.cdut.api;
 
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.annotation.BOOL;
 import com.qmth.boot.api.constant.ApiConstant;
-import com.qmth.teachcloud.exchange.common.bean.params.OpenParams;
+import com.qmth.cdut.supwisdom.CasUtils;
+import com.qmth.cdut.supwisdom.Constants;
+import com.qmth.cdut.supwisdom.LoginUser;
 import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
 import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.exchange.common.service.AuthInfoService;
 import com.qmth.teachcloud.exchange.common.service.CommonService;
-import com.qmth.teachcloud.exchange.common.util.HttpUtil;
-import com.qmth.teachcloud.exchange.common.util.JacksonUtil;
 import com.qmth.teachcloud.exchange.common.util.Result;
 import com.qmth.teachcloud.exchange.common.util.ServletUtil;
 import io.swagger.annotations.*;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
@@ -25,32 +24,26 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
 import java.util.Objects;
 import java.util.StringJoiner;
 
 /**
  * <p>
- * 西安交通大学开放接口前端控制器
+ * 成都理工大学开放接口前端控制器
  * </p>
- *
- * @author wangliang
- * @since 2022-04-26
  */
-@Api(tags = "西安交通大学开放接口Controller")
+@Api(tags = "成都理工大学开放接口Controller")
 @RestController
 @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.open}")
 @Validated
 public class OpenApiController {
     private static final Logger log = LoggerFactory.getLogger(OpenApiController.class);
-    private static final String ACCESS_TOKEN_URL = "http://org.xjtu.edu.cn/openplatform/oauth/getAccessToken";
-    private static final String USER_INFO_URL = "http://org.xjtu.edu.cn/openplatform/oauth/open/getUserInfo";
-    private static final String LOGOUT_URL = "http://org.xjtu.edu.cn/openplatform/oauth/logout";
-//    private static final String RETURN_URL = "https://org.xjtu.edu.cn/openplatform/login.html";
-    private static final String schoolCode = "xjtu";//测试学校code,正式改成xjtu
+    private static final String schoolCode = "cdut";//测试学校code,成都理工大学
 
     @Resource
     CommonService commonService;
@@ -64,112 +57,89 @@ public class OpenApiController {
     @Value("${cas.config.returnUrl}")
     String returnUrl;
 
-    @ApiOperation(value = "西安交通大学cas鉴权接口")
+    @ApiOperation(value = "成都理工大学cas鉴权接口")
     @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = Result.class)})
     @RequestMapping(value = "/authentication", method = RequestMethod.GET)
     @Aac(auth = BOOL.FALSE)
-    public void authentication(@ApiParam(value = "工号") @RequestParam(required = false) String code,
-                               @ApiParam(value = "系统参数") @RequestParam(required = false) String state,
-                               @ApiParam(value = "用户类型") @RequestParam(required = false) String userType,
-                               @ApiParam(value = "员工工号") @RequestParam(required = false) String employeeNo,
-                               @ApiParam(value = "返回url") @RequestParam(required = false) String returnUrl) throws IOException {
-        if ((Objects.isNull(code) || Objects.equals(code, ""))
-                || (Objects.isNull(employeeNo) || Objects.equals(employeeNo, ""))) {
-            throw ExceptionResultEnum.ERROR.exception("请先通过学校地址登录");
-        }
+    public void sso(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        HttpSession session = request.getSession();
+        String targetUrl = CasUtils.getTargetUrl(request);
         authInfoService.appHasExpired(schoolCode);
+        if (CasUtils.isLogin(session)) {
+            LoginUser loginUser = (LoginUser) session.getAttribute(Constants.LOGIN_USER_KEY);
+            String account = loginUser.getAccount();
 
-        Map<String, Object> accessTokenParams = new LinkedHashMap<>();
-        accessTokenParams.put("code", code);
-        String accessTokenResult = HttpUtil.post(ACCESS_TOKEN_URL, accessTokenParams, null);
-        String accessToken = null, gsessionId = null;
-
-        //获取accessToken
-        if (Objects.nonNull(accessTokenResult)) {
-            log.info("accessTokenResult:{}", JacksonUtil.parseJson(accessTokenResult));
-            JSONObject jsonObject = JSONObject.parseObject(accessTokenResult);
-            JSONObject object = jsonObject.getJSONObject("data");
-            String message = jsonObject.getString("message");
-            if (Objects.nonNull(object) && Objects.nonNull(message) && Objects.equals(message, "成功")) {
-                accessToken = object.getString("accessToken");
-                gsessionId = object.getString("gsessionId");
+            String sessionId = session.getId();
+            if (StringUtils.isNotBlank(sessionId)) {
+                StringJoiner stringJoiner = new StringJoiner("");
+                stringJoiner.add(logoutUrl).add(SystemConstant.GET_UNKNOWN).add("sessionId")
+                        .add(SystemConstant.GET_EQUAL).add(sessionId);
+                returnUrl = stringJoiner.toString();
             } else {
-                throw ExceptionResultEnum.ERROR.exception(message);
+                throw ExceptionResultEnum.ERROR.exception("sessionId为空");
             }
-        }
+            commonService.redirectLogic(account, schoolCode, returnUrl, null);
+        } else {
+            if (CasUtils.hasTicket(request)) {
+                LoginUser loginUser = CasUtils.getLoginUser(request);
+                if (loginUser.isLogin() && doLogin(loginUser, request)) {
+                    CasUtils.login(loginUser, session);
 
-        OpenParams openParams = null;
-        //获取用户信息
-        if (Objects.nonNull(accessToken)) {
-            String userInfoResult = HttpUtil.post(USER_INFO_URL, null, accessToken);
-            if (Objects.nonNull(userInfoResult)) {
-                log.info("userInfoResult:{}", JacksonUtil.parseJson(userInfoResult));
-                openParams = new OpenParams();
-//                openParams.setResult(JacksonUtil.parseJson(userInfoResult));
-                JSONObject jsonObject = JSONObject.parseObject(userInfoResult);
-                JSONObject object = jsonObject.getJSONObject("data");
-                String message = jsonObject.getString("message");
-                JSONArray userTypeJsonArray = object.getJSONArray("userTypes");
-                JSONArray deptInfoJsonArray = object.getJSONArray("deptInfos");
-                if (Objects.nonNull(object) && Objects.nonNull(message) && Objects.equals(message, "成功")) {
-                    openParams.setOrgName(object.getString("orgName"));
-                    if (Objects.nonNull(userTypeJsonArray) && userTypeJsonArray.size() > 0) {
-                        JSONObject userTypeJsonObject = userTypeJsonArray.getJSONObject(0);
-                        openParams.setName(userTypeJsonObject.getString("memberName"));
-                        Integer userTypeRole = userTypeJsonObject.getInteger("userType");
-                        if (Objects.nonNull(userTypeRole) && userTypeRole.intValue() == 1) {
-                            openParams.setRoleName("学生");
-                        } else if (Objects.nonNull(userTypeRole) && userTypeRole.intValue() == 2) {
-                            openParams.setRoleName("教职工");
-                        }
-                    }
-                    if (Objects.nonNull(deptInfoJsonArray) && deptInfoJsonArray.size() > 0) {
-                        JSONObject deptInfoJsonArrayJsonObject = deptInfoJsonArray.getJSONObject(0);
-                        openParams.setDeptName(deptInfoJsonArrayJsonObject.getString("deptName"));
-                    }
+                    String account = loginUser.getAccount();
+                    commonService.redirectLogic(account, schoolCode, returnUrl, null);
                 } else {
-                    throw ExceptionResultEnum.ERROR.exception(message);
+                    String loginUrl = CasUtils.getLoginUrl(request);
+                    response.sendRedirect(loginUrl);
+                    // TODO 可选:业务系统可根据实际情况进行处理
+//                    response.sendRedirect(CasUtils.getErrorUrl(request));
                 }
+            } else {
+                String loginUrl = CasUtils.getLoginUrl(request);
+                response.sendRedirect(loginUrl);
             }
         }
-
-        //登出
-        if (Objects.nonNull(gsessionId)) {
-            StringJoiner stringJoiner = new StringJoiner("");
-            stringJoiner.add(logoutUrl).add(SystemConstant.GET_UNKNOWN).add("gSessionId")
-                    .add(SystemConstant.GET_EQUAL).add(gsessionId);
-            returnUrl = stringJoiner.toString();
-        } else {
-            throw ExceptionResultEnum.ERROR.exception("gSessionId为空");
-        }
-
-        commonService.redirectLogic(employeeNo, schoolCode, returnUrl, Objects.nonNull(openParams) ? JacksonUtil.parseJson(openParams) : null);
     }
 
     @ApiOperation(value = "西安交通大学cas鉴权退出接口")
     @RequestMapping(value = "/authentication/logout", method = RequestMethod.GET)
     @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = Result.class)})
     @Aac(auth = BOOL.FALSE)
-    public void logout(@ApiParam(value = "sessionId", required = true) @RequestParam String gSessionId) throws IOException {
+    public void logout(@ApiParam(value = "sessionId", required = true) @RequestParam String sessionId) throws IOException {
         if (Objects.isNull(logoutUrl) || Objects.equals(logoutUrl, "")) {
             throw ExceptionResultEnum.PARAMS_ERROR.exception("鉴权退出地址不存在");
         }
-        if (Objects.isNull(gSessionId) || Objects.equals(gSessionId, "")) {
+        if (Objects.isNull(sessionId) || Objects.equals(sessionId, "")) {
             throw ExceptionResultEnum.PARAMS_ERROR.exception("sessionId为空");
         }
         authInfoService.appHasExpired(schoolCode);
-        Map<String, Object> logoutParams = new LinkedHashMap<>();
-        logoutParams.put("gSessionId", gSessionId);
-        String logoutResult = HttpUtil.post(LOGOUT_URL, logoutParams, null);
-        if (Objects.nonNull(logoutResult)) {
-            log.info("logoutResult:{}", JacksonUtil.parseJson(logoutResult));
-            JSONObject jsonObject = JSONObject.parseObject(logoutResult);
-            String message = jsonObject.getString("message");
-            if (Objects.nonNull(message) && Objects.equals(message, "成功")) {
-                HttpServletResponse response = ServletUtil.getResponse();
-                response.setHeader("Access-Control-Allow-Origin", SystemConstant.PATH_MATCH);
-                response.sendRedirect(returnUrl);
-            }
+
+        HttpServletRequest request = ServletUtil.getRequest();
+        HttpServletResponse response = ServletUtil.getResponse();
+        if (doLogout(request)) {
+            HttpSession session = request.getSession();
+            CasUtils.logout(session);
+            response.sendRedirect(CasUtils.getLogoutUrl(request));
+        } else {
+            response.sendRedirect(CasUtils.getLoginUrl(request));
         }
     }
+
+    public boolean doLogin(LoginUser loginUser, HttpServletRequest request) {
+        HttpSession session = request.getSession();
+        ServletContext application = session.getServletContext();
+        // 如果使用了Spring可以用下面的方法获取spring的context对象
+        // WebApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(application);
+        // 如果需要使用SpringMVC上下文、可以用下面的方法获取springMVC的context对象
+        // WebApplicationContext mvcContext = RequestContextUtils.getWebApplicationContext(request);
+
+        // TODO 需要业务系统重写
+
+
+        return true;
+    }
+
+    public boolean doLogout(HttpServletRequest request) {
+        return true;
+    }
+
 }

+ 192 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/CasUtils.java

@@ -0,0 +1,192 @@
+package com.qmth.cdut.supwisdom;
+
+import com.qmth.cdut.supwisdom.utils.Base64Utils;
+import com.qmth.cdut.supwisdom.utils.BooleanUtils;
+import com.qmth.cdut.supwisdom.utils.HttpRequestUtils;
+import com.qmth.cdut.supwisdom.utils.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+public class CasUtils {
+
+    /**
+     * 判断是否已经登录过
+     */
+    public static boolean isLogin(HttpSession session) {
+        Object isLogin = session.getAttribute(Constants.LOGIN_KEY);
+        return BooleanUtils.toBoolean(String.valueOf(isLogin));
+    }
+
+    public static String getBasePath(HttpServletRequest request) {
+        String scheme = request.getScheme();
+        String serverName = request.getServerName();
+        int serverPort = request.getServerPort();
+        String contextPath = request.getContextPath();
+
+        // 判断是否配置了显式端口
+        boolean explicit_port = Constants.CLIENT_SYSTEM_EXPLICIT_PORT != null
+                && !"".equals(Constants.CLIENT_SYSTEM_EXPLICIT_PORT);
+
+        if (explicit_port) {
+            try {
+                serverPort = Integer
+                        .parseInt(Constants.CLIENT_SYSTEM_EXPLICIT_PORT);
+            } catch (Exception e) {
+
+                // 异常时赋值,方便双方排查问题
+                serverPort = 19000;
+            }
+
+            String url = scheme + "://" + serverName + ":" + serverPort
+                    + contextPath + "/";
+            return url;
+
+        } else {
+            if ((serverPort == 80) || (serverPort == 443)) {
+
+                String url = scheme + "://" + serverName + contextPath
+                        + "/";
+                return url;
+            } else {
+                String url = scheme + "://" + serverName + ":" + serverPort
+                        + contextPath + "/";
+                return url;
+            }
+        }
+
+    }
+
+    /**
+     * 获取TargetUrl
+     */
+    public static String getTargetUrl(HttpServletRequest request) {
+        String basePath = getBasePath(request);
+
+        // 获取请求中的targetUrl
+        String targetUrl = request.getParameter(Constants.TARGET_URL_KEY);
+
+        if (StringUtils.isEmpty(targetUrl)) {
+            // 若不存在,则使用默认页面作为targetUrl
+            targetUrl = basePath + Constants.DEF_TARGET_URI;
+        } else {
+            // 判断target是否编码
+            if (targetUrl.startsWith(Constants.BASE64_PREFIX)) {
+                targetUrl = targetUrl.substring(Constants.BASE64_PREFIX.length());
+                targetUrl = Base64Utils.decodeBase64Str(targetUrl);
+            }
+        }
+        return targetUrl;
+    }
+
+    /**
+     * 判断票据是否存在
+     */
+    public static boolean hasTicket(HttpServletRequest request) {
+        Object ticket = request.getParameter(Constants.TICKET_KEY);
+
+        // System.out.println("ticket = " + ticket);
+        return ticket != null
+                && !StringUtils.isEmpty(String.valueOf(ticket));
+    }
+
+    public static String getURLEncodeServiceUrl(HttpServletRequest request)
+            throws UnsupportedEncodingException {
+
+        // 编码成系统可识别的加密串
+        String targetUrl = getTargetUrl(request);
+        String base64TargetUrl = Base64Utils.encodeBase64Str(targetUrl);
+
+        String serviceUrlRoot = getBasePath(request)
+                + Constants.SSO_LOGIN_URI;
+
+        String serviceUrl = serviceUrlRoot + "?" + Constants.TARGET_URL_KEY
+                + "=" + Constants.BASE64_PREFIX + base64TargetUrl;
+        return URLEncoder.encode(serviceUrl, Constants.UTF_8_STR);
+    }
+
+    /**
+     * 获取Cas登录Url 登录成功后返回票据
+     */
+    public static String getLoginUrl(HttpServletRequest request)
+            throws UnsupportedEncodingException {
+        String encodeServiceUrl = getURLEncodeServiceUrl(request);
+
+        return Constants.CAS_LOGIN_URL + "?" + Constants.SERVICE_KEY + "="
+                + encodeServiceUrl;
+    }
+
+    /**
+     * 获取校验票据Url
+     */
+    public static String getServiceValidateUrl(HttpServletRequest request)
+            throws UnsupportedEncodingException {
+
+        String encodeServiceUrl = getURLEncodeServiceUrl(request);
+        Object ticket = request.getParameter(Constants.TICKET_KEY);
+
+        // System.out.println("ticket = " + ticket);
+
+        return Constants.CAS_VALIDATE_URL + "?" + Constants.TICKET_KEY
+                + "=" + ticket + "&" + Constants.SERVICE_KEY + "="
+                + encodeServiceUrl;
+    }
+
+    public static LoginUser getLoginUser(HttpServletRequest request)
+            throws IOException {
+        String serviceValidateUrl = getServiceValidateUrl(request);
+
+        // System.out.println("serviceValidateUrl = " + serviceValidateUrl);
+
+        String casUserInfoXml = HttpRequestUtils.doGet(serviceValidateUrl);
+
+        casUserInfoXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + casUserInfoXml;
+
+        System.out.println("casUserInfoXml = " + casUserInfoXml);
+        return new LoginUser(casUserInfoXml);
+    }
+
+    /**
+     * 获取登出地址
+     */
+    public static String getLogoutUrl(HttpServletRequest request)
+            throws UnsupportedEncodingException {
+        // 获取本次请求的根Path
+        String loginUrlRoot = getBasePath(request)
+                + Constants.SSO_LOGIN_URI;
+        String encodeLoginUrlRoot = URLEncoder.encode(loginUrlRoot,
+                Constants.UTF_8_STR);
+
+        return Constants.CAS_LOGOUT_URL + "?" + Constants.SERVICE_KEY + "="
+                + encodeLoginUrlRoot;
+    }
+
+    /**
+     * 集成失败页
+     */
+    public static String getErrorUrl(HttpServletRequest request)
+            throws UnsupportedEncodingException {
+
+        return Constants.SSO_ERROR_URI;
+    }
+
+    /**
+     * 写入单页面登录判断标志
+     */
+    public static void login(LoginUser loginUser, HttpSession session) {
+        session.setAttribute(Constants.LOGIN_KEY, true);
+        session.setAttribute(Constants.LOGIN_USER_KEY, loginUser);
+    }
+
+    /**
+     * 移出单页面登录判断标志
+     */
+    public static void logout(HttpSession session) {
+        session.removeAttribute(Constants.LOGIN_KEY);
+        session.removeAttribute(Constants.LOGIN_USER_KEY);
+    }
+
+}

+ 55 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/Constants.java

@@ -0,0 +1,55 @@
+package com.qmth.cdut.supwisdom;
+
+import java.nio.charset.Charset;
+
+public interface Constants {
+
+    // CAS根地址
+    String CAS_BASE_PATH = "https://cas.paas.cdut.edu.cn/cas/";
+
+    // 业务系统需要显式使用的端口配置,包括80端口,如果不需要配置显式端口,则配置空字符串""即可
+    String CLIENT_SYSTEM_EXPLICIT_PORT = "";
+
+    // CAS票据验证地址
+    String CAS_VALIDATE_URL = CAS_BASE_PATH + "serviceValidate";
+
+    // CAS登录地址
+    String CAS_LOGIN_URL = CAS_BASE_PATH + "login";
+
+    // CAS注销地址
+    String CAS_LOGOUT_URL = CAS_BASE_PATH + "logout";
+
+    //登录成功默认跳转地址
+    String DEF_TARGET_URI = "sso/index.jsp";
+
+    // 业务系统认证集成改造之后的登录URI
+    String SSO_LOGIN_URI = "sso/login.jsp";
+
+    // 业务系统认证集成失败提示页
+    String SSO_ERROR_URI = "error.jsp";
+
+    // REQUEST中获取需要跳转URL的KEY
+    String TARGET_URL_KEY = "targetUrl";
+
+    // SESSION中判断是否登录的KEY
+    String LOGIN_KEY = "isSupwisdomCasLogin";
+    String LOGIN_USER_KEY = "supwisdomCasLoginUser";
+
+    // REQUEST中获取票据的KEY
+    String TICKET_KEY = "ticket";
+
+    // CAS Server验证成功后需跳转客户端Url的Key
+    String SERVICE_KEY = "service";
+
+    // BASE64编码的前缀
+    String BASE64_PREFIX = "base64";
+
+    // 默认编码字符串格式
+    String UTF_8_STR = "UTF-8";
+
+    // 默认编码
+    Charset UTF_8 = Charset.forName(UTF_8_STR);
+
+    // Ticket验证超时时间
+    int CONNECT_TIMEOUT = 5000;
+}

+ 182 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/LoginUser.java

@@ -0,0 +1,182 @@
+package com.qmth.cdut.supwisdom;
+
+import com.qmth.cdut.supwisdom.utils.IOUtils;
+import com.qmth.cdut.supwisdom.utils.StringUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+
+public class LoginUser {
+
+    public static final String CAS_PREFIX = "cas:";
+    public static final String LOGIN_SUCCESS_KEY = CAS_PREFIX + "authenticationSuccess";
+    public static final String ACCOUNT_KEY = CAS_PREFIX + "user";
+    public static final String ATTRIBUTES_KEY = CAS_PREFIX + "attributes";
+
+    private String account;
+
+    private String ssoAccount;
+    private String deptName;
+    private String idCard;
+    private String studentNo;
+    private String remark;
+    private String localAccount;
+    private String tel;
+    private String dicOrgId;
+    private String nick;
+    private String email;
+    private String staffNo;
+    private String name;
+    private String deptCode;
+    private String dn;
+    private String mobile;
+    private String typeCode;
+    private String type;
+    private String typeName;
+
+    public LoginUser(String loginUserXmlStr) {
+        if (StringUtils.isEmpty(loginUserXmlStr))
+            return;
+        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
+                .newInstance();
+        InputStream in = null;
+        try {
+            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+            in = IOUtils.toInputStream(loginUserXmlStr, Constants.UTF_8);
+            Document rootDoc = docBuilder.parse(in);
+            NodeList successNodeList = rootDoc.getElementsByTagName(LOGIN_SUCCESS_KEY);
+            if (successNodeList.getLength() > 0) {
+                Node successNode = successNodeList.item(0);
+                Document successDocument = successNode.getOwnerDocument();
+                NodeList accountNodeList = successDocument.getElementsByTagName(ACCOUNT_KEY);
+                if (accountNodeList != null && accountNodeList.getLength() > 0) {
+                    Node accountNode = accountNodeList.item(0);
+                    Node accountText = accountNode.getFirstChild();
+                    this.account = accountText.getNodeValue();
+                }
+                NodeList attrsNodeList = successDocument.getElementsByTagName(ATTRIBUTES_KEY);
+                if (attrsNodeList.getLength() > 0) {
+                    Node attrsNode = attrsNodeList.item(0);
+                    if (attrsNode.hasChildNodes()) {
+                        Document attrsDoc = attrsNode.getOwnerDocument();
+                        Field[] fields = getClass().getDeclaredFields();
+                        for (Field field : fields) {
+                            String fieldName = field.getName();
+                            String attrTagName = CAS_PREFIX + fieldName;
+                            NodeList attrNodeList = attrsDoc.getElementsByTagName(attrTagName);
+                            if (attrNodeList.getLength() > 0) {
+                                Node attrNode = attrNodeList.item(0);
+                                Node attrText = attrNode.getFirstChild();
+                                if (attrText != null) {
+                                    field.set(this, attrText.getNodeValue().trim());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            // 解析用户信息失败!
+            e.printStackTrace();
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
+    }
+
+    public String getAccount() {
+        return account;
+    }
+
+    public String getSsoAccount() {
+        return ssoAccount;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public String getIdCard() {
+        return idCard;
+    }
+
+    public String getStudentNo() {
+        return studentNo;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public String getLocalAccount() {
+        return localAccount;
+    }
+
+    public String getTel() {
+        return tel;
+    }
+
+    public String getDicOrgId() {
+        return dicOrgId;
+    }
+
+    public String getNick() {
+        return nick;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public String getStaffNo() {
+        return staffNo;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDeptCode() {
+        return deptCode;
+    }
+
+    public String getDn() {
+        return dn;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public String getTypeCode() {
+        return typeCode;
+    }
+
+    public void setTypeCode(String typeCode) {
+        this.typeCode = typeCode;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getTypeName() {
+        return typeName;
+    }
+
+    public void setTypeName(String typeName) {
+        this.typeName = typeName;
+    }
+
+    public boolean isLogin() {
+        return account != null && account.length() != 0;
+    }
+}

+ 185 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/utils/Base64Utils.java

@@ -0,0 +1,185 @@
+package com.qmth.cdut.supwisdom.utils;
+
+public abstract class Base64Utils {
+
+    private static final byte[] ENC_TAB_BYTES = new byte[64];
+
+    static {
+        int j = 0;
+        for (byte i = 'A'; i <= 'Z'; i++) {
+            ENC_TAB_BYTES[j] = i;
+            j++;
+        }
+        for (byte i = 'a'; i <= 'z'; i++) {
+            ENC_TAB_BYTES[j] = i;
+            j++;
+        }
+        for (byte i = '0'; i <= '9'; i++) {
+            ENC_TAB_BYTES[j] = i;
+            j++;
+        }
+        ENC_TAB_BYTES[j++] = '+';
+        ENC_TAB_BYTES[j] = '/';
+    }
+
+    public static String encodeBase64Str(String str) {
+        byte[] bytes = StringUtils.getBytes(str);
+        return encodeBase64Str(bytes);
+    }
+
+    public static String encodeBase64Str(byte[] bytes) {
+        byte[] base64Bytes = encodeBase64(bytes);
+        return StringUtils.newString(base64Bytes);
+    }
+
+    public static byte[] encodeBase64(byte[] bytes) {
+        byte[] base64Bytes;
+        int modulus = bytes.length % 3;
+        if (modulus == 0) {
+            base64Bytes = new byte[(4 * bytes.length) / 3];
+        } else {
+            base64Bytes = new byte[4 * ((bytes.length / 3) + 1)];
+        }
+        int dataLength = (bytes.length - modulus);
+        int a1;
+        int a2;
+        int a3;
+        for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {
+            a1 = bytes[i] & 0xff;
+            a2 = bytes[i + 1] & 0xff;
+            a3 = bytes[i + 2] & 0xff;
+            base64Bytes[j] = ENC_TAB_BYTES[(a1 >>> 2) & 0x3f];
+            base64Bytes[j + 1] = ENC_TAB_BYTES[((a1 << 4) | (a2 >>> 4)) & 0x3f];
+            base64Bytes[j + 2] = ENC_TAB_BYTES[((a2 << 2) | (a3 >>> 6)) & 0x3f];
+            base64Bytes[j + 3] = ENC_TAB_BYTES[a3 & 0x3f];
+        }
+        int b1;
+        int b2;
+        int b3;
+        int d1;
+        int d2;
+        switch (modulus) {
+            case 0:
+                break;
+            case 1:
+                d1 = bytes[bytes.length - 1] & 0xff;
+                b1 = (d1 >>> 2) & 0x3f;
+                b2 = (d1 << 4) & 0x3f;
+                base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1];
+                base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2];
+                base64Bytes[base64Bytes.length - 2] = '=';
+                base64Bytes[base64Bytes.length - 1] = '=';
+                break;
+            case 2:
+                d1 = bytes[bytes.length - 2] & 0xff;
+                d2 = bytes[bytes.length - 1] & 0xff;
+                b1 = (d1 >>> 2) & 0x3f;
+                b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
+                b3 = (d2 << 2) & 0x3f;
+                base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1];
+                base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2];
+                base64Bytes[base64Bytes.length - 2] = ENC_TAB_BYTES[b3];
+                base64Bytes[base64Bytes.length - 1] = '=';
+                break;
+        }
+        return base64Bytes;
+    }
+
+    private static final byte[] DEC_TAB_BYTES = new byte[128];
+
+    static {
+        for (int i = 0; i < 128; i++) {
+            DEC_TAB_BYTES[i] = (byte) -1;
+        }
+        for (int i = 'A'; i <= 'Z'; i++) {
+            DEC_TAB_BYTES[i] = (byte) (i - 'A');
+        }
+        for (int i = 'a'; i <= 'z'; i++) {
+            DEC_TAB_BYTES[i] = (byte) (i - 'a' + 26);
+        }
+        for (int i = '0'; i <= '9'; i++) {
+            DEC_TAB_BYTES[i] = (byte) (i - '0' + 52);
+        }
+        DEC_TAB_BYTES['+'] = 62;
+        DEC_TAB_BYTES['/'] = 63;
+    }
+
+    public static String decodeBase64Str(String data) {
+        byte[] base64Bytes = StringUtils.getBytes(data);
+        return decodeBase64Str(base64Bytes);
+    }
+
+    public static String decodeBase64Str(byte[] base64Bytes) {
+        byte[] bytes = decodeBase64(base64Bytes);
+        return StringUtils.newString(bytes);
+    }
+
+    public static byte[] decodeBase64(byte[] base64Bytes) {
+        byte[] bytes;
+        byte b1;
+        byte b2;
+        byte b3;
+        byte b4;
+        base64Bytes = discardNonBase64Bytes(base64Bytes);
+        if (base64Bytes[base64Bytes.length - 2] == '=') {
+            bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 1];
+        } else if (base64Bytes[base64Bytes.length - 1] == '=') {
+            bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 2];
+        } else {
+            bytes = new byte[((base64Bytes.length / 4) * 3)];
+        }
+        for (int i = 0, j = 0; i < (base64Bytes.length - 4); i += 4, j += 3) {
+            b1 = DEC_TAB_BYTES[base64Bytes[i]];
+            b2 = DEC_TAB_BYTES[base64Bytes[i + 1]];
+            b3 = DEC_TAB_BYTES[base64Bytes[i + 2]];
+            b4 = DEC_TAB_BYTES[base64Bytes[i + 3]];
+            bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));
+            bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));
+            bytes[j + 2] = (byte) ((b3 << 6) | b4);
+        }
+        if (base64Bytes[base64Bytes.length - 2] == '=') {
+            b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]];
+            b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]];
+            bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));
+        } else if (base64Bytes[base64Bytes.length - 1] == '=') {
+            b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]];
+            b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]];
+            b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]];
+            bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));
+            bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));
+        } else {
+            b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]];
+            b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]];
+            b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]];
+            b4 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 1]];
+            bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));
+            bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));
+            bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);
+        }
+        return bytes;
+    }
+
+    private static byte[] discardNonBase64Bytes(byte[] datas) {
+        byte[] temp = new byte[datas.length];
+        int bytesCopied = 0;
+        for (byte data : datas) {
+            if (isValidBase64Byte(data)) {
+                temp[bytesCopied++] = data;
+            }
+        }
+        byte[] newData = new byte[bytesCopied];
+        System.arraycopy(temp, 0, newData, 0, bytesCopied);
+        return newData;
+    }
+
+    private static boolean isValidBase64Byte(byte b) {
+        if (b == '=') {
+            return true;
+        } else if ((b < 0) || (b >= 128)) {
+            return false;
+        } else if (DEC_TAB_BYTES[b] == -1) {
+            return false;
+        }
+        return true;
+    }
+}

+ 80 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/utils/BooleanUtils.java

@@ -0,0 +1,80 @@
+package com.qmth.cdut.supwisdom.utils;
+
+public abstract class BooleanUtils {
+
+    public static boolean toBoolean(final String str) {
+        return toBooleanObject(str) == Boolean.TRUE;
+    }
+
+    public static Boolean toBooleanObject(final String str) {
+        if (str.equals("true")) {
+            return Boolean.TRUE;
+        }
+        switch (str.length()) {
+            case 1: {
+                final char ch0 = str.charAt(0);
+                if (ch0 == 'y' || ch0 == 'Y' || ch0 == 't' || ch0 == 'T') {
+                    return Boolean.TRUE;
+                }
+                if (ch0 == 'n' || ch0 == 'N' || ch0 == 'f' || ch0 == 'F') {
+                    return Boolean.FALSE;
+                }
+                break;
+            }
+            case 2: {
+                final char ch0 = str.charAt(0);
+                final char ch1 = str.charAt(1);
+                if ((ch0 == 'o' || ch0 == 'O') && (ch1 == 'n' || ch1 == 'N')) {
+                    return Boolean.TRUE;
+                }
+                if ((ch0 == 'n' || ch0 == 'N') && (ch1 == 'o' || ch1 == 'O')) {
+                    return Boolean.FALSE;
+                }
+                break;
+            }
+            case 3: {
+                final char ch0 = str.charAt(0);
+                final char ch1 = str.charAt(1);
+                final char ch2 = str.charAt(2);
+                if ((ch0 == 'y' || ch0 == 'Y') && (ch1 == 'e' || ch1 == 'E')
+                        && (ch2 == 's' || ch2 == 'S')) {
+                    return Boolean.TRUE;
+                }
+                if ((ch0 == 'o' || ch0 == 'O') && (ch1 == 'f' || ch1 == 'F')
+                        && (ch2 == 'f' || ch2 == 'F')) {
+                    return Boolean.FALSE;
+                }
+                break;
+            }
+            case 4: {
+                final char ch0 = str.charAt(0);
+                final char ch1 = str.charAt(1);
+                final char ch2 = str.charAt(2);
+                final char ch3 = str.charAt(3);
+                if ((ch0 == 't' || ch0 == 'T') && (ch1 == 'r' || ch1 == 'R')
+                        && (ch2 == 'u' || ch2 == 'U')
+                        && (ch3 == 'e' || ch3 == 'E')) {
+                    return Boolean.TRUE;
+                }
+                break;
+            }
+            case 5: {
+                final char ch0 = str.charAt(0);
+                final char ch1 = str.charAt(1);
+                final char ch2 = str.charAt(2);
+                final char ch3 = str.charAt(3);
+                final char ch4 = str.charAt(4);
+                if ((ch0 == 'f' || ch0 == 'F') && (ch1 == 'a' || ch1 == 'A')
+                        && (ch2 == 'l' || ch2 == 'L')
+                        && (ch3 == 's' || ch3 == 'S')
+                        && (ch4 == 'e' || ch4 == 'E')) {
+                    return Boolean.FALSE;
+                }
+                break;
+            }
+            default:
+                break;
+        }
+        return null;
+    }
+}

+ 57 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/utils/HttpRequestUtils.java

@@ -0,0 +1,57 @@
+package com.qmth.cdut.supwisdom.utils;
+
+import com.qmth.cdut.supwisdom.Constants;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.*;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+public abstract class HttpRequestUtils {
+
+    public static String doGet(String urlStr) throws IOException {
+        URL url = new URL(urlStr);
+        InputStream in = null;
+        HttpURLConnection conn = null;
+        try {
+            trustEveryone();
+            conn = (HttpURLConnection) url.openConnection();
+            conn.setConnectTimeout(Constants.CONNECT_TIMEOUT);
+            conn.connect();
+            in = conn.getInputStream();
+            return IOUtils.toString(in, Constants.UTF_8);
+        } finally {
+            IOUtils.close(conn);
+            IOUtils.closeQuietly(in);
+        }
+    }
+
+    public static void trustEveryone() {
+
+        try {
+            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+                public boolean verify(String hostname, SSLSession session) {
+                    return true;
+                }
+            });
+
+            SSLContext context = SSLContext.getInstance("TLS");
+            context.init(null, new X509TrustManager[]{new X509TrustManager() {
+                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+                }
+
+                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+                }
+
+                public X509Certificate[] getAcceptedIssuers() {
+                    return new X509Certificate[0];
+                }
+            }}, new SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 75 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/utils/IOUtils.java

@@ -0,0 +1,75 @@
+package com.qmth.cdut.supwisdom.utils;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.nio.charset.Charset;
+
+public abstract class IOUtils {
+
+    private static final int EOF = -1;
+
+    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+    public static void close(URLConnection conn) {
+        if (conn instanceof HttpURLConnection) {
+            ((HttpURLConnection) conn).disconnect();
+        }
+    }
+
+    public static void closeQuietly(InputStream input) {
+        closeQuietly((Closeable) input);
+    }
+
+    public static void closeQuietly(Closeable closeable) {
+        try {
+            if (closeable != null) {
+                closeable.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+
+    public static String toString(InputStream input, Charset encoding)
+            throws IOException {
+        StringWriter sw = new StringWriter();
+        copy(input, sw, encoding);
+        return sw.toString();
+    }
+
+    public static void copy(InputStream input, Writer output,
+                            Charset encoding) throws IOException {
+        encoding = encoding == null ? Charset.defaultCharset() : encoding;
+        InputStreamReader in = new InputStreamReader(input, encoding);
+        copy(in, output);
+    }
+
+    public static int copy(Reader input, Writer output) throws IOException {
+        long count = copyLarge(input, output);
+        if (count > Integer.MAX_VALUE) {
+            return -1;
+        }
+        return (int) count;
+    }
+
+    public static long copyLarge(Reader input, Writer output)
+            throws IOException {
+        return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
+    }
+
+    public static long copyLarge(Reader input, Writer output, char[] buffer)
+            throws IOException {
+        long count = 0;
+        int n;
+        while (EOF != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            count += n;
+        }
+        return count;
+    }
+
+    public static InputStream toInputStream(String input, Charset encoding) {
+        return new ByteArrayInputStream(input.getBytes());
+    }
+}

+ 19 - 0
cdut-exchange/src/main/java/com/qmth/cdut/supwisdom/utils/StringUtils.java

@@ -0,0 +1,19 @@
+package com.qmth.cdut.supwisdom.utils;
+
+public abstract class StringUtils {
+
+    public static boolean isEmpty(CharSequence cs) {
+        return cs == null || cs.length() == 0;
+    }
+
+    public static byte[] getBytes(final String string) {
+        if (string == null) {
+            return null;
+        }
+        return string.getBytes();
+    }
+
+    public static String newString(final byte[] bytes) {
+        return bytes == null ? null : new String(bytes);
+    }
+}

+ 3 - 4
cdut-exchange/src/main/resources/application.properties

@@ -7,14 +7,14 @@ server.tomcat.max-connections=2500
 server.tomcat.uri-encoding=UTF-8
 
 #\u9879\u76EE\u540D\u79F0
-spring.application.name=xjtu-exchange
+spring.application.name=cdut-exchange
 
 #\u6570\u636E\u6E90\u914D\u7F6E
 db.host=localhost
 db.port=3306
-db.name=exchange-v1.0.0
+db.name=exchange-api-v1.0.0
 db.username=root
-db.password=123456789
+db.password=root
 
 #redis\u6570\u636E\u6E90\u914D\u7F6E
 com.qmth.redis.host=${db.host}
@@ -75,6 +75,5 @@ com.qmth.solar.access-secret=y7AO6W0TOdTF8HpWBwGHbp3wfIHsmUKr
 #com.qmth.solar.license=/Volumes/extend/\u542F\u660E/\u5206\u5E03\u5F0F\u5370\u5237/\u5206\u5E03\u5F0F\u5370\u5237&\u6559\u7814\u5206\u6790v3.1.0/tc-dev-wl.lic
 
 cas.config.teachcloudPrintLoginUrl=https://*.teach-cloud-test.com/#/login-open
-#cas.config.teachcloudPrintLoginUrl=http://192.168.10.99:8056/#/login-open
 cas.config.logoutUrl=https://dj-xian.qmth.com.cn/api/open/authentication/logout
 cas.config.returnUrl=https://org.xjtu.edu.cn/openplatform/oauth/authorize?appId=1548&redirectUri=http://10.184.206.15/api/open/authentication&responseType=code&scope=user_info&state=1234