1.说说虚拟地址空间有哪些部分
虚拟地址空间分为内核空间和用户空间,其中每个进程都有独自的虚拟地址空间,这里指的是用户空间,内核空间是所有进程共享的, 所以只有一个,内核进行初始化时,会创建内核空间映射,并且是线性映射,即内核一整块内核空间页,一对一的映射到物理内存上。
当程序进行系统调用时,发生中断,会将用户态转化为内核态,用户栈中转化为内核栈,用户栈信息放到内核栈中,中断结束后恢复现场,其中,内核空间的资源都是共享的。
2VueRouter基本用法是什么?
一个路由(route)就是一组映射关系(key-value),多个路由(router)被路由器所管辖,在前端路由中,key为路径,value为组件。
基本用法:
命令:npm i vue-router
应用插件:Vue.use(VueRouter)
编写router配置:
//引入VueRouter
import VueRouter from 'vue-router'
//引入Luyou 组件
import About from '../components/About'
import Home from '../components/Home'
//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
//暴露router
export default router
实现切换(active-class可配置高亮样式)
<router-link active-class="active" to="/about">About</router-link>
指定展示位置
<router-view></router-view>
路由器的两种工作模式(hash/history)
对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
hash模式:
地址中永远带着#号,不美观 。
若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
兼容性较好。
history模式:
地址干净,美观 。
兼容性和hash模式相比略差。
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
3.说一说map 和 forEach 的区别?
相同点:
-都是循环遍历数组中的每一项
-匿名函数中的this都指向window
-只能遍历数组
-每次执行匿名函数都有三个参数,当前每一项,索引值,原数组
不同点:
map()是创建一个新的数组并返回, foreach()是修改原来数组,没有返回值。
foreach()可通过callback更改原数组的值
map速度比forEach更快
map可以链式操作,forEach不可
4.CSRF攻击是什么?
CSRF指的是跨站请求伪造攻击,攻击者引导用户登录第三方网站,然后该网站向被攻击网站发送跨站请求,如果用户在被攻击网站中保存了登录状态,那么攻击者就可以利用这个登录状态,绕过后台的用户验证,冒充用户向服务器执行一些操作。
攻击类型:
- GET类型的CSRF攻击:比如在网站中的一个img标签里构建一个请求,当用户打开这个网站的时候就会自动发送请求。
- POST类型的CSRF攻击:比如构建一个表单,然后隐藏它,当用户进入这个页面时,会自动发起请求。
- 链接类型的CRSF攻击:比如在a标签的href属性里构建一个请求,然后诱导用户去点击。
如何防止CSRF攻击:
-
充分利用好 Cookie 的 SameSite 属性。
由于攻击者是通过用户的登录状态来发起CSRF攻击的,而cookie是服务器与浏览器之间进行登录状态验证的关键数据。cookie的SameSite属性有 Strict、Lax 和 None 三个值。
strict代表完全禁止第三方cookie,即如果你从A页面访问B页面,而B页面的一些Cookie设置了SameSite=strict,那么这些Cookie不会被送到B页面的服务器上,只有同源时才会发送。
Lax宽松些,如果是从第三方链接打开或者是从第三方的站点提交GET请求,都会携带Cookie,而在第三方站点中使用POST方法,或通过某些img等标签加载的URL,这些场景不会携带Cookie。
None在任何情况下都会发送Cookie数据。 -
在服务器端验证请求的来源站点。
由于 CSRF 攻击大多来自于第三方站点,因此服务器可以禁止来自第三方站点的请求。这就需要介绍 HTTP 请求头中的 Referer 和 Origin 属性了。服务器的策略是优先判断 Origin,如果请求头中没有包含 Origin 属性,再根据实际情况判断是否使用 Referer 值。 -
CSRF Token
在浏览器向服务器发起请求时,服务器生成一个 CSRF Token。CSRF Token 其实就是服务器生成的字符串,然后将该字符串植入到返回的页面中。
在浏览器端如果要发起转账的请求,那么需要带上页面中的 CSRF Token,然后服务器会验证该 Token 是否合法。如果是从第三方站点发出的请求,那么将无法获取到 CSRF Token 的值,所以即使发出了请求,服务器也会因为 CSRF Token 不正确而拒绝请求。
5.二叉树遍历编程题
首先创建二维数组,再创建队列,判断字符串中是否为空,如果是,直接返回,如果不是,将根节点加入队列,然后开始遍历,用变量size记录每一行的节点个数,然后进行循环,先将本行的记录在一个数组中,再判断其左右节点是否有值,如果有就存入queue队列循环结束后,将本行的数组存入结果数组中即可。
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
// write code here
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
if(root == null) return result;
queue.add(root);
while(!queue.isEmpty()) {
int size = queue.size();
ArrayList<Integer> r = new ArrayList<Integer>();
while(size != 0) {
TreeNode cur = queue.remove();
r.add(cur.val);
if(cur.left != null) queue.add(cur.left);
if(cur.right != null) queue.add(cur.right);
size--;
}
result.add(r);
}
return result;
}
}
6.兑换零钱编程题
本题使用的是简单动态规划,遍历范围从最低的1元开始到aim元,时间复杂度为O(n * aim),找到遍历到某元时需要的最低货币数量。
import java.util.*;
public class Solution {
/**
* 最少货币数
* @param arr int整型一维数组 the array
* @param aim int整型 the target
* @return int整型
*/
public int minMoney (int[] arr, int aim) {
// write code here
//先判断最少货币是否大于0
if(aim < 1) return 0;
//创建数组dp并初始化
int dp[] = new int[aim + 1];
Arrays.fill(dp,aim + 1);
dp[0] = 0;
for(int i = 1; i < aim + 1; i++) {
for(int j = 0; j < arr.length; j++ ) {
if(arr[j] <= i) dp[i] = Math.min(dp[i], dp[i - arr[j]] + 1);
}
}
return dp[aim] > aim ? -1 : dp[aim];
}