Yongtao's Blog

坚守 无畏 宽容 进取


  • 首页

  • 归档

  • 搜索

Redis安装

发表于 2017-10-16 | 更新于 2023-02-15 | 分类于 缓存 , Redis | 阅读次数

安装Redis

下载安装

1
2
3
4
[root@localhost src] wget http://download.redis.io/releases/redis-4.0.2.tar.gz
[root@localhost src] tar xzf redis-4.0.2.tar.gz
[root@localhost src] cd redis-4.0.2
[root@localhost src] make
阅读全文 »

资源导航

发表于 2017-10-15 | 更新于 2018-11-30 | 分类于 学习资源 | 阅读次数
富强 民主 文明 和谐
html&css基础 html&css基础 HTML5 - MDN 十天精通CSS3
jQuery手册 javascript廖雪峰 javascript进阶 javascript入门
redis教程 Python教程 Gitflow工作流 Firefox开发者工具
Docker Practice 跟阿铭学Linux V2 Windows批处理 标准SQL语法
Spring boot  Source ElasticSearch Springboot PowerShell在线教程
Java设计模式 spring cloud tests Spring cloud Hibernate 5.0 User Guide
正则表达式 Elasticsearch: 权威指南 Kibana 用户手册

Oracle Scott表MySQL 版本

发表于 2017-10-09 | 更新于 2023-02-20 | 分类于 数据库 , MySQL | 阅读次数

Oracle Scott表MySQL 版本

表

涉及bonus dept emp salgrade几张表,可以作为SQL学习测试的Demo表.

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
Navicat MySQL Data Transfer

Source Server : localhost
Source Server Version : 50173
Source Host : 192.168.91.129:3306
Source Database : oracle_scott

Target Server Type : MYSQL
Target Server Version : 50173
File Encoding : 65001

Date: 2017-10-09 13:29:54
*/
阅读全文 »

Nonce与重放攻击

发表于 2017-07-25 | 更新于 2023-02-20 | 分类于 WEB技术 | 阅读次数

重放攻击(Replay attack)是一种网络攻击,它恶意的欺诈性的重复或拖延正常的数据传输。 —— [ Wikipedia ]

使用签名认证方式设计的RESTFul API,当请求信息被第三方拦截之后,由于其含有认证信息,当再次发起该请求时,如果没有相应的保护机制,请求会再次通过验证,造成重放攻击的风险。

为避免该问题,通常情况下的做法是:

每次发起HTTP请求,都需要加上timestamp参数,然后把timestamp和其他参数一起进行签名。服务端接收到HTTP请求后,将客户端timestamp与服务端当前时间比较,判断是否超过了请求有效期,比如60s,如果超过了则认为是非法的请求。

如此一来从第一次请求发起的时间算起,60s之后再访问时会被服务端拒绝,但是在60s有效期内,依然可以发起重放攻击。

解决方案:

  1. 客户端生成一个随机字符串Nonce (Number used once), 并且参与签名
  2. 服务端第一次接收到请求,去缓存中查询Nonce是否存在
    1. 如果不存在,则认为在有效期内该请求第一次访问,放行;然后将Nonce保存在缓存中,并设置有效期为60s,60s之后该Nonce缓存失效被清除
    2. 如果存在,则认为在有效期内该请求Replay,拒绝提供访问

需要保证的是有效期内并发请求生成随机数的唯一性。

Interview

发表于 2017-07-18 | 更新于 2023-02-20 | 分类于 面试 | 阅读次数

推断打印结果

1
2
3
4
5
6
7
8
9
10
public static void main(String args[]) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;

System.out.println((a == c));
System.out.println((a == e));
}

结果:

1
2
true
false

解析:由于b的值确定且被final修饰,会被当做编译期常量使用,即编译期出现b变量的地方会被直接替换,
替换后,a和c都指向字符串常量池中的hello2地址,故a==c为true;而String e = d + 2;会被编译器转换为类似于 String e = new StringBuilder(d).append(“2”); 故 a==e为false.

请画出a,b,c,d内存分布图

1
2
3
4
5
6
public static void main(String args[]) {
int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };
int[] c = { 7, 8, 9 };
int[][] d = { a, b, c };
}

解析:

判断输出结果

I
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Example {
String str = new String("Hello");
char[] ch = {'a','b','c'};

public static void main(String[] args) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);
System.out.println(ex.ch);
}

public void change(String str, char[] ch){
str= "Hi";
ch[1]= 'h';
}
}

运行结果:

1
2
Hello
ahc

解析:

II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Person {

public int age;

public static void changeEmployee(Person employee) {
employee = new Person();
employee.age = 1000;
}

public static void main(String[] args) {
Person employee = new Person();
employee.age = 100;
changeEmployee(employee);
System.out.println(employee.age);
}
}

哪些操作是原子性操作

1
2
3
4
x = 10;         //语句1
y = x; //语句2
x++; //语句3
x = x + 1; //语句4
1
x = 10;

解析:注意y = x,需要读取和赋值,并非原子性操作。

以下代码是否有问题,并解释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Example {
public static void main(String[] args) {
Outputer outputer = new Outputer();
final Thread t0 = new Thread(() -> {
outputer.output2("How are you?");
});
final Thread t1 = new Thread(() -> {
outputer.output("Fine, thank you.");
});
t0.start();
t1.start();
}

static class Outputer {
public synchronized void output(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}

public static synchronized void output2(String name) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}

解析:
ouput和output2两个方法分别使用类对象和类实例对象的锁,两个线程不会竞争同一个锁资源,因而不会产生互斥,从而导致输出混乱。

SQL查询

员工表emp:

empno ename job mgr hiredate sal comm deptno
7369 SMITH CLERK 7902 1980-12-17 800.00 NULL 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-04-02 2975.00 NULL 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 NULL 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 NULL 10
7788 SCOTT ANALYST 7566 1987-07-13 3000.00 NULL 20
7839 KING PRESIDENT NULL 1981-11-17 5000.00 NULL 10
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-07-13 1100.00 NULL 20
7900 JAMES CLERK 7698 1981-12-03 950.00 NULL 30
7902 FORD ANALYST 7566 1981-12-03 3000.00 NULL 20
7934 MILLER CLERK 7782 1982-01-23 1300.00 NULL 10

部门表dept:

deptno dname loc
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
查询部门表在员工表中不存在的部门号;
1
2
3
4
5
6
SELECT d.deptno
FROM dept d
WHERE NOT EXISTS (
SELECT NULL
FROM emp e
WHERE d.deptno = e.deptno);
查询工资高于部门平均工资的员工;
1
2
3
4
5
6
7
SELECT e2.ename,e2.sal,e2.deptno,r1._avg
FROM emp e2
INNER JOIN (
SELECT e1.deptno, AVG(e1.sal) AS _avg
FROM emp e1
GROUP BY e1.deptno) r1 ON e2.deptno = r1.deptno AND e2.sal > r1._avg
ORDER BY e2.deptno ASC, e2.sal DESC;
查询部门工资前三名的员工;
1
2
3
4
5
6
7
SELECT t0.deptno, t0.ename, t0.sal
FROM emp t0
WHERE (
SELECT COUNT(1)
FROM emp t1
WHERE t0.deptno = t1.deptno AND t1.sal >= t0.sal) <= 3
ORDER BY deptno,sal DESC;

解析: 员工工资排名前3,可以转换为: 工资大于等于自己的人数(count)小于等于3

1…101112
wangyt

wangyt

白日不到处,青春恰自来
苔花如米小,也学牡丹开

58 日志
29 分类
45 标签
RSS
GitHub 微博
Creative Commons
  • How2j
  • 寒泉子
  • 朱双印
© 2016 - 2023 wangyt