面试问题
Posted mrneng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试问题相关的知识,希望对你有一定的参考价值。
1、 pageHelper分页插件的使用
Mybatis的plugin实现了Interceptor接口,可以在插件中获得执行的sql语句,在sql语句中添加limit语句,实现分页。
使用原理:pageHelper会使用ThreadLocal获取同一线程中的变量信息,各个线程之间的Threadlocal不会相互干扰,也就是Thread1中的ThreadLocal1之后获取到Tread1中的变量的信息,不会获取到Thread2中的信息。所以在多线程环境下,各个Threadlocal之间相互隔离,可以实现,不同thread使用不同的数据源或不同的Thread中执行不同的SQL语句
所以,PageHelper利用这一点通过拦截器获取到同一线程中的预编译好的SQL语句之后将SQL语句包装成具有分页功能的SQL语句,并将其再次赋值给下一步操作,所以实际执行的SQL语句就是有了分页功能的SQL语句
2、 防止Sql注入
1) Sql注入攻击的总体思路
1、 寻找到SQL注入的位置
2、 判断服务器类型和后台数据库类型
3、 针对不通的服务器和数据库特点进行SQL注入攻击
方法:
1、PreparedStatement
采用预编译语句集,它内置了处理sql注入的能力,只要使用它的setXXX方法传值即可。
好处:(1)代码的可读性和可维护性
(2)PreparedStatement能够提高 性能
(3)极大的提高了安全性
Sql注入只对sql语句的编译过程有破坏作用,而PreparedStatement已经编译好了,执行阶段只是把输入串作为数据处理,而不会对sql进行解析,准备,因此避免了sql注入的过程。
2、使用正则表达式过滤传入的参数
检测SQL meta-characters的正则表达式 :
/(\%27)|(’)|(--)|(\%23)|(#)/ix
修正检测SQL meta-characters的正则表达式 :/((\%3D)|(=))[^ ]*((\%27)|(’)|(--)|(\%3B)|(:))/i
典型的SQL 注入攻击的正则表达式 :/w*((\%27)|(’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
检测SQL注入,UNION查询关键字的正则表达式 :/((\%27)|(’))union/ix(\%27)|(’)
检测MS SQL Server SQL注入攻击的正则表达式:
/exec(s|+)+(s|x)pw+/ix
3、字符串过滤
比较通用的一个方法:
(||之间的参数可以根据自己程序的需要添加)
public static boolean sql_inj(String str)
{
String inj_str = "‘|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[] = split(inj_str,"|");
for (int i=0 ; i < inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])>=0)
{
return true;
}
}
return false;
}
4、jsp中调用函数判断是否包含非法字符
防止slq从url注入
public class sql_inj{
public static boolean sql_inj(String str)
{
String inj_str = "‘|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
//这里的东西还可以自己添加
String[] inj_stra=inj_str.split("\|");
for (int i=0 ; i < inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])>=0)
{
return true;
}
}
return false;
}
}
5、jsp页面判断代码
使用js在客户端进行不安全字符的屏蔽,检查是否含有”‘”,”\”,”/”
Mybatis中模糊查询防止sql注入
#{xxx},使用的是PreparedStatement,会有类型转换,所以比较安全;
${xxx},使用字符串拼接,有sql注入的问题
select * from t_user where name like concat(‘%‘, #{name}, ‘%‘)
4、 单点登录
用户的一次登录就能得到其他所有系统的信任,那么关键的是如何产生和存储那个信任
存储信任
验证信任
集群环境登录:
第一种:以cookie作为凭证媒介
存在的问题:Cookie不安全
不能跨域实现免登陆
解决的办法:1.对Cookie进行加密(源码不泄露的情况下)
Cookie的加密和解密:DES加密和解密、MD5加密和解密(不可逆)工具类直接用
(DES加密的原理:使用了一个56位的密钥以及附加的8位奇偶校验位,产生最大64位的分组大小。迭代的分组密码,将加密的文本分成了两份,使用子密钥对其中一半应用循环功能,然后将输出与另外一半进行“异或”运算;接着进行交换这两半,一直循环下去)
- 跨域实现免登陆:配置session共享
- 使用Tomcat自身的同步机制复制session到集群中的其他服务器
Tomcat的同步机制是广播形式,也就是说集群中所有Tomcat都是相同的session信息,但是这种情况下,Tomcat越多,效率就会越低,官方给出的最佳集群数量是5台Tomcat
2.使用缓存服务器集中存储session信息达到session共享需求。不管在那台服务器登录成功之后,都会将session信息保存在统一的Redis缓存服务器中,获取用户登录信息。
存储信任
验证信任
只要解决了以上的问题,达到了开头讲得效果就可以说是SSO。最简单实现SSO的方法就是用Cookie,实现流程如下所示:
不然发现以上的方案是把信任存储在客户端的Cookie里,这种方法虽然实现方便但立马会让人质疑两个问题:
Cookie不安全
不能跨域免登
对于第一个问题一般都是通过加密Cookie来处理,第二个问题是硬伤,其实这种方案的思路的就是要把这个信任关系存储在客户端,要实现这个也不一定只能用Cookie,用flash也能解决,flash的Shared Object API就提供了存储能力。
一般说来,大型系统会采取在服务端存储信任关系的做法,实现流程如下所示:
以上方案就是要把信任关系存储在单独的SSO系统(暂且这么称呼它)里,说起来只是简单地从客户端移到了服务端,但其中几个问题需要重点解决:
如何高效存储大量临时性的信任数据
如何防止信息传递过程被篡改
如何让SSO系统信任登录系统和免登系统
对于第一个问题,一般可以采用类似与memcached的分布式缓存的方案,既能提供可扩展数据量的机制,也能提供高效访问。对于第二个问题,一般采取数字签名的方法,要么通过数字证书签名,要么通过像md5的方式,这就需要SSO系统返回免登URL的时候对需验证的参数进行md5加密,并带上token一起返回,最后需免登的系统进行验证信任关系的时候,需把这个token传给SSO系统,SSO系统通过对token的验证就可以辨别信息是否被改过。对于最后一个问题,可以通过白名单来处理,说简单点只有在白名单上的系统才能请求生产信任关系,同理只有在白名单上的系统才能被免登录。
1、你们用dubbo是怎么设计接口的?参数返回值是什么?为什么这么设计?
硬件通过通讯模块TCP协议传过一个数据包,你需要接受并解析,解析规则已有
2、在开发过程中,多个使用zookeeper,怎么解决端口冲突的问题
3、插入数据的时候,如果有重复的就变成修改,怎么实现
ON DUPLICATE KEY UPDATE(当出现DUPLICATE KEY主键重复错误的时候触发Update操作,当然要求就是表在设计的时候一定要有主键primary key)
$sql = "insert into weixin_user(wx_id, wx_name, wx_state, wx_info, wx_lasttime) values (‘$wx_id‘, ‘$wx_name‘, ‘$wx_state‘, ‘$wx_info‘, NOW()) ON DUPLICATE KEY UPDATE wx_name=‘$wx_name‘, wx_state = ‘$wx_state‘, wx_info = ‘$wx_info‘, wx_lasttime = NOW();";
5、Dubbo的底层原理:
- client一个线程调用远程接口,生成一个唯一的ID(比如一段随机字符串,UUID等),Dubbo是使用AtomicLong(原子变量,加了同步锁的)从0开始累计数字的;
- 将打包的方法调用信息(如调用的接口名称,方法名称,参数值列表等),和处理结果的回调对象callback,全部封装在一起,组成一个对象object;
- 向专门存放调用信息的全局ConcurrentHashMap里面put(ID, object)
- 将ID和打包的方法调用信息封装成一对象connRequest,使用iosession.write(connRequest)异步发送出去;
- 当前线程再使用callback的get()方法试图获取远程返回的结果,在get()内部,则使用synchronized获取回调对象callback的锁, 再先检测是否已经获取到结果,如果没有,然后调用callback的wait()方法,释放callback上的锁,让当前线程处于等待状态。
- 服务端接收到请求并处理后,将结果(此结果中包含了前面的ID,即回传)发送给客户端,客户端socket连接上专门监听消息的线程收到消息,分析结果,取到ID,再从前面的ConcurrentHashMap里面get(ID),从而找到callback,将方法调用结果设置到callback对象里。
- 监听线程接着使用synchronized获取回调对象callback的锁(因为前面调用过wait(),那个线程已释放callback的锁了),再notifyAll(),唤醒前面处于等待状态的线程继续执行(callback的get()方法继续执行就能拿到调用结果了),至此,整个过程结束。
以上是关于面试问题的主要内容,如果未能解决你的问题,请参考以下文章