先摘录一段单点登录的定义,来自百度百科。

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

单点登录的基本流程:用户发起单点登陆请求----->>通过请求信息获取用户编号usercode------>>利用usercode在系统中注册登录信息------->>利用注册的信息单点登录到NC系统

以下类请根据具体项目需求开放和注释部分代码

一、登录请求处理类

/*** NC单点登录Servlet类*/
public class NCLoginServlet extends HttpServlet {/** 字段描述 */private static final long serialVersionUID = 1L;// 传输协议private String scheme = null;// NC主机地址private String serverName = null;// NC主机端口private int serverPort = 80;// 传递过来的用户账号private String usercode = null;// 屏幕宽度private String width = null;// 屏幕高度private String height = null;public static String getFromBASE64(String s) {if (s == null)return null;BASE64Decoder decoder = new BASE64Decoder();try {byte[] b = decoder.decodeBuffer(s);return new String(b);} catch (Exception e) {return null;}}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {try {// 接收前台传递过来的信息scheme = request.getScheme(); // 传输协议serverName = request.getServerName(); // NC主机地址serverPort = request.getServerPort(); // NC主机端口width = request.getParameter("width"); // 屏幕宽度height = request.getParameter("height");// 屏幕高度NcWebTools ncweb = new NcWebTools();// 取得传递过来的域用户信息,解密//usercode = NcWebTools.SSOUnicodeToString(request.getParameter("ssoid"));usercode = request.getParameter("ssoid");//CA二次认证
//          if(!ncweb.isVerifyPass(usercode)){//              String url = scheme + "://" + serverName + ":" + serverPort + "/ncsso/error/error106.jsp";
//              response.sendRedirect(url); // 重定向至错误页面
//              return;
//          }// 检查用户是否存在于NC系统中String username = ncweb.isExistInNC(usercode);if (username == null) {String url = scheme + "://" + serverName + ":" + serverPort + "/error.jsp";response.sendRedirect(url); // 重定向至错误页面return;}// 检查用户是否已分配权限
//          if (!ncweb.isExistRole(usercode)) {//              String url = scheme + "://" + serverName + ":" + serverPort + "/ncsso/error/error103.jsp";
//              response.sendRedirect(url); // 重定向至错误页面
//              return;
//          }// 重定向至NC主界面sendToNC(response, ncweb);} catch (Exception ex) {ex.printStackTrace();throw new ServletException(ex.getMessage());}}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}/*** * <P>* 重定向至NC主界面* </P>* * @param response* @throws Exception*/private void sendToNC(HttpServletResponse response, NcWebTools ncweb) throws Exception {// 随机生成一个keyString randomKey = IDMaker.makeID(20);// 组装注册请求urlString ssurl = scheme + "://" + serverName + ":" + serverPort + "/service/RegisterServlet?key=" + randomKey + "&language=simpchn" // 语言+ "&usercode=" + usercode // 用户编码+ "&width=" + width // 屏幕宽度+ "&height=" + height; // 屏幕高度// 获取登录公司String pk_corp = ncweb.getCorpByUsercode(usercode);if (pk_corp != null && !"".equals(pk_corp)) {ssurl += "&pkcorp=" + pk_corp;}Logger.debug(ssurl);ncweb.connect(ssurl); // 注册// 拼装NC单点登录URLString url = scheme + "://" + serverName + ":" + serverPort + "/login.jsp?key=" + randomKey + "&width=" + width // 屏幕宽度+ "&height=" + height; // 屏幕高度;
//      String url = "Uclient://start/"+scheme + "://" + serverName + ":" + serverPort+"/?ssoKey="+ randomKey/*+"&uiloader=nc.ui.sm.login.Loader3"*/;// 重定向到指定的地址
//      response.sendRedirect(url);PrintWriter w = response.getWriter();w.print(url);//w.print("<html><head><script>window.location='"+url+"';</script></head><body></body></html>");return;}
}

二、各项辅助类

  1. IDMaker 用于生成注册信息(key)
/*** key生成器*/
public class IDMaker {private final static String CODES = "0123456789abcdefghijklmnopqrstuvwxyz+";private final static String DIGIT_CODES = "0123456789+";private final static String CHAR_CODES = "abcdefghijklmnopqrstuvwxyz+";// 组成ID基本元素的数量public static final int ID_ELEMENT_COUNT = 36;public static final int TYPE_ALL = 0;public static final int TYPE_CHAR = 1;public static final int TYPE_DIGIT = 2;/*** 返回长度为idLen的编码* * @return java.lang.String* @param idLen*            int*/public final static String makeID(int idLen, int idType) {if (idType == TYPE_CHAR) {return makeCharID(idLen);}if (idType == TYPE_DIGIT) {return makeDigitID(idLen);}return makeID(idLen);}/*** 返回长度为idLen的编码* * @return java.lang.String* @param idLen*            int*/private final static String makeDigitID(int idLen) {if (idLen < 1 || idLen > 64) {return null;}String id = null;if (id == null)id = "";int n;StringBuffer sb = new StringBuffer(id);for (int i = 0; i < idLen; i++) {n = (int) (java.lang.Math.random() * 10);sb.append(DIGIT_CODES.substring(n, n + 1));}return sb.toString();}/*** 返回长度为idLen的编码* * @return java.lang.String* @param idLen*            int*/private final static String makeCharID(int idLen) {if (idLen < 1 || idLen > 64) {return null;}String id = null;if (id == null)id = "";int n;StringBuffer sb = new StringBuffer(id);for (int i = 0; i < idLen; i++) {n = (int) (java.lang.Math.random() * 26);sb.append(CHAR_CODES.substring(n, n + 1));}return sb.toString();}/*** 返回长度为idLen的编码* * @return java.lang.String* @param idLen*            int*/public final static String makeID(int idLen) {if (idLen < 1 || idLen > 64) {return null;}String id = null;if (id == null)id = "";int n;StringBuffer sb = new StringBuffer(id);for (int i = 0; i < idLen; i++) {n = (int) (java.lang.Math.random() * 36);sb.append(CODES.substring(n, n + 1));}return sb.toString();}/*** 根据传入的ID,按照编码生成规则生成下一个ID。 ID组成包括 0-9 A-Z 字母不区分大小写* * @see:需要参见的其* @return java.lang.String* @param id*            java.lang.String*/public final static String nextID(String id) {// 转换String 到 Char类型int len = id.length();char[] ids = new char[len];id.getChars(0, len, ids, 0);// 如果是'0'-'8' 'a'-'y' 'A'-'Y'的字符if ((ids[len - 1] >= 'a' && ids[len - 1] < 'z') || (ids[len - 1] >= 'A' && ids[len - 1] < 'Z') || (ids[len - 1] >= '0' && ids[len - 1] < '9')) {ids[len - 1] += 1;}// 如果是'9'字符else if (ids[len - 1] == '9') {ids[len - 1] = 'A';}// 只能是'z'或'Z'else {ids[len - 1] = '0';if (len == 1) {// 如果当前的字符串为"z"时,下一个Id应当为"10"。return "10";}if (len > 1) // 进位return nextID(id.substring(0, len - 1)) + '0';}String nextID = String.copyValueOf(ids);return nextID;}/*** 根据传入的ID,按照编码生成规则生成下一个ID。 ID组成包括 0-9 A-Z 字母不区分大小写* * @see:需要参见的其* @return java.lang.String* @param id*            java.lang.String*/private final static String nextDigitID(String id) {// 转换String 到 Char类型int len = id.length();char[] ids = new char[len];id.getChars(0, len, ids, 0);// 如果是'0'-'8' 的字符if ((ids[len - 1] >= '0' && ids[len - 1] < '9')) {ids[len - 1] += 1;}// 只能是'9'else {ids[len - 1] = '0';if (len > 1) // 进位return nextDigitID(id.substring(0, len - 1)) + '0';}String nextID = String.copyValueOf(ids);return nextID;}/*** 根据传入的ID,按照编码生成规则生成下一个ID。 ID组成包括 0-9 A-Z 字母不区分大小写* * @see:需要参见的其* @return java.lang.String* @param id*            java.lang.String*/private final static String nextCharID(String id) {// 转换String 到 Char类型int len = id.length();char[] ids = new char[len];id.getChars(0, len, ids, 0);// 如果是'a'-'y' 'A'-'Y'的字符if ((ids[len - 1] >= 'a' && ids[len - 1] < 'z') || (ids[len - 1] >= 'A' && ids[len - 1] < 'Z')) {ids[len - 1] += 1;}// 只能是'z'或'Z'else {ids[len - 1] = 'a';if (len > 1) // 进位return nextCharID(id.substring(0, len - 1)) + 'a';}String nextID = String.copyValueOf(ids);return nextID;}/*** 根据传入的ID,按照编码生成规则生成下一个ID。 ID组成包括 0-9 A-Z 字母不区分大小写* * @see:需要参见的其* @return java.lang.String* @param id*            java.lang.String*/public final static String nextID(String id, int idType) {if (idType == TYPE_CHAR) {return nextCharID(id);}if (idType == TYPE_DIGIT) {return nextDigitID(id);}return nextID(id);}
}
  1. NcWebTools 用于实现在NC系统注册用户信息
/*** web工具类*/
public class NcWebTools {public HttpURLConnection connection;// 数据源public static String DATASOURCE = "nc57";// 帐套编码
//  public static String ACCOUNTCODEVALUE = "01";
//
//  // 账套名称
//  public static String ACCOUNTCODE = "测试帐套";// UAP 定义客户端CA接口类,应用实际使用时,应该有应用工厂或单例
//  public static nc.vo.uap.security.IUsbKey usbKey;NcOrclUtils db = new NcOrclUtils();/*** url链接* * @throws Exception*/public void connect(String urlString) throws Exception {try {URL url = new URL(urlString);connection = (HttpURLConnection) url.openConnection();System.out.println("开始注册单点登陆...");System.out.println(urlString);connection.connect();BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine = null;while ((inputLine = in.readLine()) != null) {System.out.println(inputLine);}in.close();System.out.println("注册单点登陆成功!");} catch (Exception e) {e.printStackTrace();throw new Exception(e.getMessage());} finally {if (connection != null) {connection.disconnect();}}}/*** 二次认证usbKey中的用户是否为要登录用户* @param usercode* @return*/
//  boolean isVerifyPass(String usercode){//      usbKey = new iTrusUsbKey();
//      //判断ukey是否插在的电脑上,相关配置文件为 nchome/resources/com/itrus/base/resource/p11config.xml
//      if(usbKey.isUsbKeyExistent()){//          //获取员工编号(证书UID),执行该方法必须为判断ukey已插入,否则返回null
//          String uid = new String(usbKey.getUserID());
//          if(usercode.equals(uid)){//              return true;
//          }
//      }
//      return false;
//  }/*** * <P>* 检查用户是否存在于NC系统中* </P>* * @param usercode* @return* @throws Exception*/String isExistInNC(String usercode) throws Exception {try {String sql = "select user_name sx from sm_user where isnull(sm_user.dr,0)=0 and UPPER(user_code) = '" + usercode.toUpperCase() + "'";String user_name = this.getString(sql);if (user_name != null && !"".equals(user_name)) {return user_name;}} catch (Exception e) {e.printStackTrace();throw new Exception(e.getMessage());}return null;}/*** * <P>* 检查用户是否已分配权限* </P>* * @param usercode* @return* @throws Exception*/boolean isExistRole(String usercode) throws Exception {// 查询数据,并填充到表模型String sql = " select count(*) count from sm_user " +" inner join sm_user_role on sm_user.cuserid=sm_user_role.cuserid "+" where  isnull(sm_user.dr,0)=0 and isnull(sm_user_role.dr,0)=0 and  UPPER(sm_user.user_code)='" + usercode.toUpperCase() + "'" + " group by sm_user_role.pk_corp ";int ir = this.getCount(sql);if (ir == 0) {return false;} else {return true;}}/*** * <P>* 根据用户编码,返回用户所在公司* </P>* * @param usercode* @return*/public String getCorpByUsercode(String usercode) {// 查询数据,并填充到表模型String sql = " select distinct sm_user_role.pk_corp "+ " from sm_user inner join sm_user_role on sm_user.cuserid = sm_user_role.cuserid " + " where isnull(sm_user.dr,0) =0 and isnull(sm_user_role.dr,0) =0 and UPPER(sm_user.user_code) = '"+ usercode.toUpperCase() + "'" + " order by sm_user_role.pk_corp ";java.util.Vector checkedData = null;try {checkedData = this.getVector(sql);} catch (Exception e) {e.printStackTrace();return null;}if (checkedData != null && (checkedData.size() > 0 && checkedData.size() <= 2)) {// 有两个公司的情况时,看其中有没有包含集团,如果不包含集团则返回null
//          if (checkedData.size() == 2) {//
//              // 公司中是否存在集团
//              boolean isExist0001 = false;
//
//              for (int i = 0; i < checkedData.size(); i++) {//
//                  String pk_corp = (String) ((Vector) checkedData.get(i)).get(0);
//
//                  if ("0001".equals(pk_corp)) {//                      isExist0001 = true;
//                  }
//              }
//
//              if (!isExist0001) {//                  return null;
//              }
//
//          }for (int i = 0; i < checkedData.size(); i++) {String pk_corp = (String) ((Vector) checkedData.get(i)).get(0);if (checkedData.size() == 1) {return pk_corp;}if (checkedData.size() == 2 && !"0001".equals(pk_corp)) { // 如果有两个公司,则返回集团外的公司return pk_corp;}}}return "1001";}/*** 获取数值型结果* * @param strSql* @return* @throws Exception*/public int getCount(String strSql) throws Exception {return db.getCount(strSql);}/*** 获取文本型结果* * @param strSql* @return* @throws Exception*/public String getString(String strSql) throws Exception {return db.getString(strSql);}/*** 获取Vector型结果* * @param args* @return* @throws Exception*/public Vector getVector(String args) throws Exception {return db.getVector(args);}}
  1. NcOrclUtils Oracle数据库访问帮助类
/*** NC 数据库 JDBC*/
public class NcOrclUtils {private String dbDriver = "oracle.jdbc.OracleDriver";private String dbUrl = "jdbc:oracle:thin:@";private java.sql.Connection conn = null;private java.sql.Statement stmt = null;private java.sql.ResultSet rs = null;public NcOrclUtils() {try {Class.forName(dbDriver);} catch (java.lang.ClassNotFoundException e) {e.printStackTrace();}}public Connection getConnection() throws java.sql.SQLException {this.conn = ConnectionFactory.getConnection(NcWebTools.DATASOURCE);return this.conn;}public ResultSet excuteQuery(String sqlStr) {if (sqlStr == null || sqlStr.equals("")) {return null;}try {this.getConnection();this.stmt = this.conn.createStatement();this.rs = this.stmt.executeQuery(sqlStr);} catch (java.sql.SQLException e) {e.printStackTrace();} finally {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}return this.rs;}public boolean excuteUpdate(String sqlStr) {if (sqlStr == null || sqlStr.equals("")) {return false;}try {this.getConnection();this.stmt = this.conn.createStatement();stmt.executeUpdate(sqlStr);} catch (java.sql.SQLException e) {e.printStackTrace();return false;} finally {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}return true;}public boolean executeUpdates(String[] sqlStrs) {try {this.getConnection();this.conn.setAutoCommit(false);this.stmt = conn.createStatement();for (int i = 0; i < sqlStrs.length; i++) {this.stmt.addBatch(sqlStrs[i]);}stmt.executeBatch();this.conn.commit();this.conn.setAutoCommit(true);} catch (SQLException e) {try {if (conn != null) {conn.rollback();}} catch (SQLException ex) {ex.printStackTrace();}e.printStackTrace();return false;} finally {try {if (stmt != null)stmt.close();} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (conn != null)conn.close();} catch (java.sql.SQLException e) {e.printStackTrace();}}return true;}/*** 获取数值型结果* * @param strSql* @return* @throws Exception*/public int getCount(String sqlStr) throws Exception {int ir = 0;if (sqlStr == null || sqlStr.equals("")) {return 0;}try {this.getConnection();this.stmt = this.conn.createStatement();this.rs = this.stmt.executeQuery(sqlStr);if (rs.next()) {ir = rs.getInt("count");}} catch (java.sql.SQLException e) {e.printStackTrace();} finally {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}return ir;}/*** 获取文本型结果* * @param strSql* @return* @throws Exception*/public String getString(String sqlStr) throws Exception {String sr = "";if (sqlStr == null || sqlStr.equals("")) {return null;}try {this.getConnection();this.stmt = this.conn.createStatement();this.rs = this.stmt.executeQuery(sqlStr);if (rs.next()) {sr = rs.getString("sx");}} catch (java.sql.SQLException e) {e.printStackTrace();} finally {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}return sr;}/*** 获取Vector型结果* * @param args* @return* @throws Exception*/public Vector getVector(String sqlStr) throws Exception {if (sqlStr == null || sqlStr.equals("")) {return null;}Vector vv = new Vector();try {this.getConnection();this.stmt = this.conn.createStatement();this.rs = this.stmt.executeQuery(sqlStr);while (rs.next()) {Vector v = new Vector();v.add(rs.getString(1));vv.add(v);}} catch (java.sql.SQLException e) {e.printStackTrace();} finally {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}return vv;}public void closeStmt() {try {if (this.stmt != null) {this.stmt.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}public void closeConnection() {try {if (this.conn != null) {this.conn.close();}} catch (java.sql.SQLException e) {e.printStackTrace();}}
}

三、接收请求

增加loginnc.jsp,通过JSP页面接收第三方系统登录请求,放入nchome\webapps\nc_web中
引用 jquery-2.0.0.min.js

<%@ page contentType="text/html; charset=GB2312"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"     "http://www.w3.org/TR/html4/loose.dtd">
<script type="text/javascript" src="jquery-2.0.0.min.js"></script>
<script type="text/javascript"> var scheme = "<%=request.getScheme()%>"; //传输协议var servername = "<%=request.getServerName()%>"; //NC主机地址var serverport = "<%=request.getServerPort()%>"; //NC主机端口var ssoToken = "<%=request.getParameter("SSOToken")%>";//ssokeyvar height = window.screen.height;//浏览器高度var width = window.screen.width;//浏览器宽度var ncurlUclient= "Uclient://start/" + scheme + "://" + servername + ":" + serverport;var ncurlIExplorer= scheme + "://" + servername + ":" + serverport;var ncurlBase = scheme + "://" + servername + ":" + serverport;var xmlHttp;var xmlHttpTONC;var key; var usercode;//用户编码window.onload = LoginNC;function LoginNC() {if (null != ssoToken) { // 通过ssoToken获取usercodedoRequestUsingGETuserCode(ssoToken);if (null != usercode&&usercode!="\r\n") { //利用usercode注册key,使用key登陆系统setTimeout(openNC, 100);} else {//usercode未取到值$("#console").html("登录信息有误,请联系管理员!");}} else {//ssoToken未取到值$("#console").html("登录信息有误,请联系管理员!");}}//单点登录NC系统的方法function openNC() {doRequestUsingGET(usercode); //通过用户名获取key值//var url = ncurlIExplorer + "/login.jsp?clienttype=portal&key=" + key;location.href = key;}//在NC中获取用户编码usercode//第三方系统大概率不会提供用于NC登录的usercode明文//通过第三方系统的接口获取NC用户的信息function doRequestUsingGETuserCode(ssoToken) {var para = "SSOToken=" + ssoToken;var queryString = ncurlBase + "/service/NCSooServlet";$.ajax({type: "POST",url: queryString,data: para,dataType: "text",async:false,success: function(result){usercode = result;}});}//在NC中注册单点登录所使用的key注册码function doRequestUsingGET(usercode) {var queryString = ncurlBase+ "/service/NCLoginServlet?scheme="+scheme+"&serverName="+servername+"&serverPort="+serverport+"&width="+width+"&height="+height+"&ssoid="+usercode;$.ajax({type: "GET",url: queryString,dataType: "text",async:false,success: function(result){key = result;}});}</script>
<html><head><meta http-equiv = "Content-Type" content = "text/html;charset=GB2312"> <title>NC登陆</title></head><body><div id = "console"></div></body>
</html>

四、配置信息

  1. exterior.xml 用于配置对远程ip访问NC系统的限制信息,存放于nchome\ierp\bin
<?xml version="1.0" encoding='gb2312'?>
<root docType="remote ip config"><remoteip>127.0.0.1</remoteip><remoteip>192.168.*.*</remoteip><timeout>20000</timeout>
</root>
  1. web.xml 用于配置新增的servlet,存放于nchome\webapps\nc_web\WEB-INF
<servlet> <servlet-name>NCLoginServlet</servlet-name><servlet-class>nc.itf.sso.Service.NCLoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>NCLoginServlet</servlet-name><url-pattern>/service/NCLoginServlet</url-pattern>
</servlet-mapping>

NC5.X系列单点登录相关推荐

  1. 初探系列 — Pharbers用于单点登录的权限架构

    一. 前言 就职公司 法伯科技是一家以数据科技为驱动, 专注于医药健康领域的循证咨询公司. 以数据科学家身份, 赋能医药行业. 让每位客户都能享受数据带来的价值, 洞察业务, 不止于数据, 让决策更精 ...

  2. 爆破专栏丨Spring Security系列教程之实现CAS单点登录上篇-概述

    作者:千锋一一哥 前言 从本章节开始,一一哥 会给各位讲解一个很常见也很重要的知识点,就是单点登录!现在的大型分布式项目,基本都会考虑实现单点登录,而且现在网上也有很多单点登录的实现方案.开源项目,但 ...

  3. 「单点登录与权限管理」系列概述

    首先,感谢几位朋友在朋友圈转发我的文章,小声的告诉你们,是我主动让他们帮忙转发的:)在朋友们的分享下,凌晨推送的一篇文章,阅读人数达到了280多,很满足,我会坚持写下去,分享工作.学习.生活中的所思所 ...

  4. java培训爆破专栏之Spring Security系列教程之实现CAS单点登录上篇-概述

    作者:千锋一一哥 前言 从本章节开始,一一哥 会给各位讲解一个很常见也很重要的知识点,就是单点登录!现在的大型分布式项目,基本都会考虑实现单点登录,而且现在网上也有很多单点登录的实现方案.开源项目,但 ...

  5. SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

    落雨 cas 单点登录 一.用户第一次访问web1应用. ps:上图少画了一条线,那一条线,应该再返回来一条,然后再到server端,画少了一步...谢谢提醒.而且,重定向肯定是从浏览器过去的.我写的 ...

  6. 轻松入门CAS系列(1)-轻松看懂企业单点登录的解决方案

    常见的企业应用情况  企业内部的信息化一般都是一个过程中的 ,起初企业为了部分管理的需要,会上线几个信息化系统:后来对这块慢慢重视,信息系统会越来越多.开始,只有一两个系统时,员工还好,靠脑袋还能记得 ...

  7. SSO场景系列:实现Microsoft AD到阿里云的单点登录

    [更新:随着RAM 2.0的上线,阿里云官网提供了对SAML Federation的官方技术文档,读者可以参考:https://help.aliyun.com/document_detail/9623 ...

  8. SSO(Single Sign On)系列(三)--CAS单点登录

    上篇文章介绍了SSO的原理以及5种基本流程,相信看完了之后不难理解单点登录,而CAS是SSO的一种实现方案,原理是一样的.下面介绍一下. CAS Server:负责完成对用户的认证工作,需要独立部署, ...

  9. SSO系列之——同域下单点登录系统介绍

    Single-Sign-On即单点登录,从一个页面登录,就可以访问其他互信系统,避免用户重新登录,例如登录了百度,则百度云等其他百度旗下其他网站均可免登录访问.在整个业务服务群中起到了辅助.集成的作用 ...

  10. 单点登录与权限管理本质:session和cookie介绍

    本篇开始写「单点登录与权限管理」系列的第一部分:单点登录与权限管理本质,这部分主要介绍相关的知识概念.抽象的处理过程.常见的实现框架.通过这部分的介绍,能够对单点登录与权限管理有整体上的了解,对其相关 ...

最新文章

  1. 智领先机 惠普推出家庭信息中心HIC
  2. 【Groovy】Groovy 脚本调用 ( Groovy 类中调用 Groovy 脚本 | 创建 GroovyShell 对象并执行 Groovy 脚本 | 完整代码示例 )
  3. c语言程序报告英汉词典,C语言电子英汉词典程序设计报告-自动化1203-李煜明.docx...
  4. 使用RMAN验证备份的有效性
  5. MapReduce:Simplified Data Processing on Large Clusters中文版from百度文库
  6. 现代优化计算方法_【公开课】供应链库存优化与需求预测管理
  7. Idea搭建一个JavaWeb项目(一)
  8. JS中Promise函数then的奥秘探究
  9. java中为什么同步_如何在Java中同步工作
  10. leetcode—25.链表排序题目leetcode总结
  11. 【FZU 2277】Change
  12. 贝莱德文化:领导者必须培养领导者
  13. java 表单字段扩展_如何从Chrome扩展程序填写网页表单中的文本字段?
  14. 常见必问面试问题一_面试自我介绍3分钟、离职原因、期望薪资…(含面试技巧和答案)
  15. 创客使用Fusion 360 - 草绘
  16. 切尔诺贝利_切尔诺贝利泰坦尼克号的自然恢复历史以及复杂系统的课程
  17. 打苹果,诉三星……陌生的它,是中国乃至全球最神秘科技公司
  18. 小米手机怎么录制视频 手机录制视频的方法
  19. 计算机视觉论文文献综述怎么找,如何有效在知网寻找属于自己课题的文献综述...
  20. 神操作 之 Mac OS prompt_status:5:command not found:wc

热门文章

  1. 天翼校园网电脑端实现共享WiFi,解决一机一账号上线的问题! 亲测有效!!!
  2. inPixio Photo Studio 11(图片编辑软件)官方正式版V11.0.7709.20526 | 超好用的图片编辑器
  3. Java发送邮件换行问题
  4. AMPL 多差产品容量限制运输模型
  5. 毕业设计 - 基于JAVA人脸识别管理系统(人脸搜索与人脸库管理)
  6. 快速打开内网服务器文件,Linux服务器局域网(内网)快速传输文件
  7. 无线鼠标全国产化电子元件推荐方案
  8. python 随机颜色
  9. 四个简单的步骤告别烦人的flash广告
  10. C语言打印九九乘法表