单点登录介绍

  ​ SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。

实现机制

  当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--token;用户再访问别的应用的时候就会将这个token带上,作为自己认证的凭据,应用系统接受到请求之后会把token送到认证系统进行校验,检查token的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了 。

  Token(令牌)

  token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。

当用户第一次登录后,服务器生成一个token并将此token返回给客户端,客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。 以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。

  简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。

  设计token的值可以有以下方式

  1. 用设备mac地址作为token
  2. 用sessionid作为token

  同域SSO原理分析

实际上,HTTP协议是无状态的,单个系统的会话由服务端Session进行维持,Session保持会话的原理是通过Cookie把sessionId写入浏览器,每次访问都会自动携带全部Cookie,在服务端读取其中的sessionId进行验证实现会话保持。同域下单点登录其实就是手写token代替sessionId进行会话认证。

  token的生成

  服务端生成token后,将token与user对象存储在Map结构中,token为Key,user对象为value,response.addCookie()生成新的Cookie,名为token,值为token的值。

  token过期移除

  将服务端的token从Map中移除,再删除浏览器端的名为token的Cookie。

同域SSO案例

  流程图如下:

    

  项目架构图如下:

    

  本例演示的是同域SSO

  test-sso-auth的访问地址是:http://check.x.com:8080/test-sso-auth

  test-sso1的访问地址是:http://demo1.x.com:8080/test-sso1

  test-sso2的访问地址是:http://demo2.x.com:8080/test-sso2

  为了测试方便,需要在hosts文件中,修改IP与域名的映射关系,如下:

 127.0.0.1 demo1.x.com
127.0.0.1 demo2.x.com
127.0.0.1 check.x.com

  test-sso-auth认证中心      

  1、新建一个Maven Web项目作为认证中心,test-sso-auth,参考:【Maven】Eclipse 使用Maven创建Java Web项目

    

  2、新建一个登录Servlet,处理登录请求,LoginServlet.java

 package com.test.sso.servlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.test.sso.util.SSOUtil; /**
* Servlet implementation class LoginServlet
*/
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String username = request.getParameter("username");
String password = request.getParameter("password");
String redirectUrl = request.getParameter("redirectUrl");
if(SSOUtil.doLogin(username, password)) {
Cookie cookie = new Cookie("sso", "123456");
// 设置到父域中,所有子域可以使用cookie
cookie.setDomain("x.com");
// cookie设置的域的最顶层
cookie.setPath("/");
response.addCookie(cookie);
response.sendRedirect(redirectUrl);
}else { //这句话的意思,是让浏览器用utf8来解析返回的数据
response.setHeader("Content-type", "text/html;charset=UTF-8");
//这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
response.setCharacterEncoding("UTF-8");
response.getWriter().print("登录失败");
}
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }

  3、新建一个验证Token的Servlet,验证Token的有效性,CheckServlet.java

 package com.test.sso.servlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.test.sso.util.SSOUtil; /**
* Servlet implementation class CheckServlet
*/
public class CheckServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username");
String password = request.getParameter("password");
boolean checkLogin = SSOUtil.checkLogin(username, password); //这句话的意思,是让浏览器用utf8来解析返回的数据
response.setHeader("Content-type", "text/html;charset=UTF-8");
//这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
response.setCharacterEncoding("UTF-8");
response.getWriter().print(checkLogin); } /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }

  4、编辑一个Util,处理登录,验证token的逻辑,SSOUtil.java

 package com.test.sso.util;

 import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; public class SSOUtil { public static String USERNAME = "admin";
public static String PASSWORD = "123456"; public static boolean doLogin(String username, String password) {
if (USERNAME.equals(username) && PASSWORD.equals(password)) {
return true;
}
return false;
} public static boolean checkLogin(String username, String password) { if ("sso".equals(username) && "123456".equals(password)) {
return true;
}
return false;
}
}

  5、编辑web.xml文件,注册相应的servlet

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>/test-sso-auth</display-name>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<display-name>LoginServlet</display-name>
<description></description>
<servlet-class>com.test.sso.servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>CheckServlet</servlet-name>
<display-name>CheckServlet</display-name>
<description></description>
<servlet-class>com.test.sso.servlet.CheckServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/check</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

  6、编辑统一登录界面,login.jsp

 <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<body>
<h2>统一登录界面</h2>
<form action="login" method="POST">
<span>用户名:</span><input type="text" name="username" />
<span>密码:</span><input type="password" name="password" />
<input type="hidden" value="${param.redirectUrl }" name="redirectUrl"/>
<input type="submit"/>
</form>
</body>
</html>

  test-sso1子系统

  1、新建一个Maven Web项目作为子系统,test-sso1,参考:【Maven】Eclipse 使用Maven创建Java Web项目   

    

  2、新建一个Servlet,逻辑为,当用户请求时,验证用户是否登录(可以用拦截器做),

    已登录情况,直接返回用户请求的界面

    未登录情况,跳转到统一登录界面进行登录

 package com.test.sso.servlet;

 import java.io.IOException;
import java.net.URLEncoder; import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.test.sso.util.HttpConnectionUtils; /**
* Servlet implementation class HomeServlet
*/
public class Home1Servlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* Default constructor.
*/
public Home1Servlet() {
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at: ").append(request.getContextPath());
// String username = request.getParameter("username");
// String password = request.getParameter("password");
boolean checkLogin = checkLogin(request);
if(checkLogin) {
// 登录-跳转到主页
request.getRequestDispatcher("home1.jsp").forward(request, response);
}else {
// 未登录-跳转的登录界面
String redirectUrl = "http://demo1.x.com:8080/test-sso1/home1"; // request.getSession().setAttribute("redirectUrl", redirectUrl);
// request.getRequestDispatcher("login.jsp").forward(request, response); response.sendRedirect("http://check.x.com:8080/test-sso-auth/login.jsp?redirectUrl=" + URLEncoder.encode(redirectUrl, "UTF-8"));
}
} private boolean checkLogin(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) { String method = HttpConnectionUtils.getMethod("http://check.x.com:8080/test-sso-auth/check?" + "username=" +cookie.getName() + "&password=" + cookie.getValue());
if("true".equals(method)) {
return true;
}
}
}
return false;
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }

    其中代码中使用的http工具类HttpConnectionUtils,参考【JAVA】通过URLConnection/HttpURLConnection发送HTTP请求的方法(一)

  3、编辑web.xml文件,注册servlet

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>/test-sso1</display-name>
<servlet>
<servlet-name>Home1Servlet</servlet-name>
<display-name>Home1Servlet</display-name>
<description></description>
<servlet-class>com.test.sso.servlet.Home1Servlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>Home1Servlet</servlet-name>
<url-pattern>/home1</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

  4、编辑用户请求界面home1.jsp

 <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Home 1 JSP</h2>
</body>
</html>

  test-sso2子系统

  搭建方式,参考上面的test-sso1子系统

  项目演示

  将test-sso-auth、test-sso1 和 test-sso2 三个项目发布到tomcat中,并启动tomcat

  流程:

  1、使用http://demo1.x.com:8080/test-sso1/home1,请求界面

  2、未登录,跳转到统一登录界面(http://check.x.com:8080/test-sso-auth/login.jsp),输出用户名/密码:admin/123456

  3、登录完成,跳转到http://demo1.x.com:8080/test-sso1/home1界面

  4、打开http://demo2.x.com:8080/test-sso2/home2,查看是否完成登录

  

跨域SSO案例

  本例演示的是跨域SSO

  test-sso-auth的访问地址是:http://check.x.com:8080/test-sso-auth

  test-sso1的访问地址是:http://demo1.a.com:8080/test-sso1

  test-sso2的访问地址是:http://demo2.b.com:8080/test-sso2

  为了测试方便,需要在hosts文件中,修改IP与域名的映射关系,如下:

 127.0.0.1 check.x.com
127.0.0.1 demo1.a.com
127.0.0.1 demo2.b.com

  为了方便,本例在上面同域SSO案例的代码上进行修改

  test-sso-auth认证中心  

  修改了LoginServlet.java,登录成功时,回调前没有写入Cookie,而是吧Cookie的值在url中传回给子系统,让子系统做逻辑处理

 package com.test.sso.servlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.test.sso.util.SSOUtil; /**
* Servlet implementation class LoginServlet
*/
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String username = request.getParameter("username");
String password = request.getParameter("password");
String redirectUrl = request.getParameter("redirectUrl");
if(SSOUtil.doLogin(username, password)) {
// Cookie cookie = new Cookie("sso", "123456");
// // 设置到父域中,所有子域可以使用cookie
// cookie.setDomain("x.com");
// // cookie设置的域的最顶层
// cookie.setPath("/");
// response.addCookie(cookie);
// response.sendRedirect(redirectUrl); response.sendRedirect(redirectUrl + "?cname=sso&cval=123456");
}else { //这句话的意思,是让浏览器用utf8来解析返回的数据
response.setHeader("Content-type", "text/html;charset=UTF-8");
//这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
response.setCharacterEncoding("UTF-8");
response.getWriter().print("登录失败");
}
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} } 

  test-sso1子系统

  1、修改业务的Servlet,Home1Servlet.java  

    修改内容:a、接收认证中心在url传过来的Cookie的值,生成Cookie并保持,且传到界面

           b、界面上,利用HTML的script标签跨域写Cookie,增加子系统b的Cookie

 package com.test.sso.servlet;

 import java.io.IOException;
import java.net.URLEncoder; import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.test.sso.util.HttpConnectionUtils; /**
* Servlet implementation class HomeServlet
*/
public class Home1Servlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 认证中心回调,验证
boolean checkSSO = checkSSO(request, response);
boolean checkLogin = checkLogin(request); if(checkLogin || checkSSO) {
// 登录-跳转到主页
request.getRequestDispatcher("home1.jsp").forward(request, response);
}else {
// 未登录-跳转的登录界面
String redirectUrl = "http://demo1.a.com:8080/test-sso1/home1"; // request.getSession().setAttribute("redirectUrl", redirectUrl);
// request.getRequestDispatcher("login.jsp").forward(request, response);
response.sendRedirect("http://check.x.com:8080/test-sso-auth/login.jsp?redirectUrl=" + URLEncoder.encode(redirectUrl, "UTF-8"));
}
} private boolean checkLogin(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) { String method = HttpConnectionUtils.getMethod("http://check.x.com:8080/test-sso-auth/check?" + "username=" +cookie.getName() + "&password=" + cookie.getValue());
if("true".equals(method)) {
request.getSession().setAttribute("canme", cookie.getName());
request.getSession().setAttribute("cval", cookie.getValue());
return true;
}
}
}
return false;
} private boolean checkSSO(HttpServletRequest request, HttpServletResponse response) {
String cname = request.getParameter("cname");
String cval = request.getParameter("cval");
if(cname != null && cname.length() > 0 && cval != null && cval.length() > 0) {
// 验证
String method = HttpConnectionUtils.getMethod("http://check.x.com:8080/test-sso-auth/check?" + "username=" +cname + "&password=" + cval);
if("true".equals(method)) {
request.getSession().setAttribute("canme", cname);
request.getSession().setAttribute("cval", cval); Cookie cookie = new Cookie(cname, cval);
// cookie设置的域的最顶层
cookie.setPath("/");
response.addCookie(cookie);
return true;
}
}
return false;
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }

  2、界面上,利用HTML的script标签跨域写Cookie,增加子系统b的Cookie,服务端增加对应的Servlet服务,AddCookieServlet.java

 package com.test.sso.servlet;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* Servlet implementation class AddTokenServlet
*/
public class AddCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cname = request.getParameter("cname");
String cval = request.getParameter("cval");
Cookie cookie = new Cookie(cname, cval);
// cookie设置的域的最顶层
cookie.setPath("/");
response.addCookie(cookie);
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
} }

  3、修改home1.jsp界面

 <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Home 1 JSP</h2>
</body> <script type="text/javascript" src="http://demo2.b.com/addCookie?cname=${params.cname }&cval=${params.cval }"></script> </html>

  4、在web.xml中注册新增的Servlet

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>/test-sso1</display-name>
<servlet>
<servlet-name>Home1Servlet</servlet-name>
<display-name>Home1Servlet</display-name>
<description></description>
<servlet-class>com.test.sso.servlet.Home1Servlet</servlet-class>
</servlet>
<servlet>
<description>
</description>
<display-name>AddCookieServlet</display-name>
<servlet-name>AddCookieServlet</servlet-name>
<servlet-class>com.test.sso.servlet.AddCookieServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>Home1Servlet</servlet-name>
<url-pattern>/home1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AddCookieServlet</servlet-name>
<url-pattern>/addCookie</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

  test-sso2子系统

  搭建方式,参考上面的test-sso1子系统

  项目演示

  将test-sso-auth、test-sso1 和 test-sso2 三个项目发布到tomcat中,并启动tomcat

  流程:

  1、使用http://demo1.a.com:8080/test-sso1/home1,请求界面

  2、未登录,跳转到统一登录界面(http://check.x.com:8080/test-sso-auth/login.jsp),输出用户名/密码:admin/123456

  3、登录完成,跳转到http://demo1.a.com:8080/test-sso1/home1界面

  4、打开http://demo2.b.com:8080/test-sso2/home2,查看是否完成登录

    

【Java】单点登录(SSO)的更多相关文章

  1. Atitit. 单点登录sso 的解决方案 总结

    Atitit.  单点登录sso 的解决方案 总结 1. 系统应用场景and SSO模式选型 2 2. 系统应用的原则与要求 2 2.1. 开发快速简单::绝大部分系统来说,开发快速简单为主 2 2. ...

  2. CAS单点登录(SSO)完整教程

    转:http://blog.csdn.net/frinder/article/details/7969925 CAS单点登录(SSO)完整教程(2012-02-01更新) 一.教程说明 前言 教程目的 ...

  3. java单点登录系统CAS的简单使用

    转:http://blog.csdn.net/yunye114105/article/details/7997041 背景 有几个相对独立的java的web应用系统, 各自有自己的登陆验证功能,用户在 ...

  4. cas 单点登录(SSO)实验之二: cas-client

    cas 单点登录(SSO)实验之二: cas-client 参考文章: http://my.oschina.net/indestiny/blog/200768#comments http://wenk ...

  5. cas 单点登录(SSO)之一: jasig cas-server 安装

    cas 单点登录(SSO)实验之一: jasig cas-server 安装 参考文章: http://my.oschina.net/indestiny/blog/200768#comments ht ...

  6. 单点登录SSO的实现原理 (转)

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...

  7. 单点登录(一)-----理论-----单点登录SSO的介绍和CAS+选型

    什么是单点登录(SSO) 单点登录主要用于多系统集成,即在多个系统中,用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无须多次登录. 单点登录(Single Sign On),简称为 ...

  8. cas 单点登录(SSO)之中的一个: jasig cas-server 安装

    cas 单点登录(SSO)实验之中的一个: jasig cas-server 安装 參考文章: http://my.oschina.net/indestiny/blog/200768#comments ...

  9. cas单点登录 SSO 的实现原理

    原文出处: cutesource   欢迎分享原创到伯乐头条 单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户 ...

  10. 单点登录 SSO 的实现原理

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任. 单点登录在大型网站里使用 ...

随机推荐

  1. python函数调用时参数传递方式

    python函数调用时参数传递方式 C/C++参数传递方式 对于C程序员来说,我们都知道C在函数调用时,采用的是值传递,即形参和实参分配不同的内存地址,在调用时将实参的值传给实参,在这种情况下,在函数 ...

  2. SpringBoot项目打成jar在linux后台运行

    --关闭客户端依然进程存在 nohup java -jar spring-boot-hello-1.0.jar 1>/dev/null 2>&1 & --Ctrl+C后不会 ...

  3. ES6中Number中的扩展

    1.Number.parseInt() , Number.parseFloat() 在ES6中将parseInt()和parseFloat()都移植到Number对象上去,方法的行为保持不变. // ...

  4. QA流程

    一.测试人员的介入时间 1.当产品经理与业务人员制定需求的时候,测试人员不宜介入: 2.当下一期的需求原型出来以后,这个时候就进入了需求评审.需求分析阶段,此时,测试人员应该介入: 3.当开发人员在编 ...

  5. SparkSQL读写外部数据源-json文件的读写

    object JsonFileTest { def main(args: Array[String]): Unit = { val spark = SparkSession .builder() .m ...

  6. AD域与信任关系

    域与信任关系:信任关系分为两种,一种是林中信任关系,另一种是林之间的信任关系. 林中信任关系的特点: 注意:林中信任关系还可以分为两种:一种是父子信任,还有一种是树根信任. 父子信任:在同一个树域之中 ...

  7. 数论--扩展欧几里得exgcd

    算法思想 我们想求得一组\(x,y\)使得 \(ax+by = \gcd(a,b)\) 根据 \(\gcd(a,b) = \gcd(b,a\bmod b)\) 如果我们现在有\(x',y'\) 使得 ...

  8. solidworks 学习 (三)

    汽车轮毂三维建模

  9. c++ 去掉所有空格及换行符

    string get_string(string res){ //删除换行符 int r = res.find('\r\n'); while (r != string::npos) { if (r ! ...

  10. know thself