发表于: 2021-03-06 23:12:15

1 1266


今天完成的事情:

拦截器

深度思考



明天计划的事情:

任务4,5总结

任务6




遇到的问题:

以下




收获:


拦截器是什么?


在spring-mvc.xml中添加,具体配置如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.scorpios.atcrowdfunding.web.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.scorpios.atcrowdfunding.web.AuthInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>



它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。


由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

===========

过滤器(Filter)是什么?



我们在配置web.xml时,总会配置下面一段设置字符编码,不然会导致乱码问题:
<!--字符过滤器-->
<!-- filter必须作用于dispatcher -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

配置这个地方的目的,是让所有的请求都需要进行字符编码的设置,下面来介绍一下Filter。



(1)过滤器(Filter):它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。



===============

拦截器(Interceptor)的使用

1)、实现HandlerInterceptor接口。
2)、继承实现了HandlerInterceptor接口的类。比如Spring已经提供的实现了HandlerInterceptor接口的
抽象类HandlerInterceptorAdapter



2、关于HandlerInterceptor接口

该接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。



(1)preHandle (预处理)(HttpServletRequest request, HttpServletResponse response, Object handle) 方法。顾名思义,该方法将在请求处理之前进行调用。SpringMVC中的Interceptor是链式的调用的,在一个应用中或者是在一个请求中可以同时存在多个Interceptor。每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是Boolean类型的,当它返回为false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true 时就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller 方法。




(2)postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法。由preHandle方法的解释我们知道这个方法包括后面要说到的afterCompletion方法都只能是在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用。**postHandle方法,顾名思义就是在当前请求进行处理之后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。**postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明的Interceptor的postHandle方法反而会后执行。




(3)afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。



===============
===============

Interceptor的使用


(1)、登陆拦截器
public class InterceptUtil implements HandlerInterceptor {
@Autowired
UserService userService;
private static Logger logger = LoggerFactory.getLogger(InterceptUtil.class);
//密钥
private static final String SECRE="1234";
/**
* 在控制器执行之前完成业务逻辑操作
* 方法的返回值决定逻辑是否继续执行, true,表示继续执行, false, 表示不再继续执行。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
//从请求中获取cookie, 判断当前用户是否已经登陆
Cookie cookie = CookieUtil.getCookie(request.getCookies(), "token");
//判断客户端是否有cookie
if (cookie != null) {
//cookie得到token
String value = URLDecoder.decode(cookie.getValue(), "utf-8");
logger.info("从客户端得到的taken" + value);
//解密token
Claims token = JWTUtil.parseJWT(value, SECRE);
if(token!=null){
return true;
}else {
return false;
}
} else {
logger.info("用户没有登录");
//如果没有检测到登录状态就重定向到登录界面
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
}
/**
* Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
/**
* 在完成视图渲染之后,执行此方法。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}



登陆拦截器在访问每个URL的时候都会进行是否登陆判断,如果没登陆的话,就直接跳转到登陆页,并不会跳转到要访问的路径(数据可能获取不到)。在登陆的控制器中,需要把用户信息放在cookie中,然后在登陆拦截器中,采用如下方式获取Cookie cookie = CookieUtil.getCookie(request.getCookies(), "token");




(2)、在SpringMVC中注册这些拦截器


<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,按顺序执行 -->
<mvc:interceptor>
<!--<mvc:mapping path="/**"/> &lt;!&ndash; 拦截所有的url包括子url路径 &ndash;&gt;-->
<mvc:mapping path="/u/**"/><!-- 拦截所有的url包括子url路径 -->
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>
<mvc:exclude-mapping path="/images/**"/>
<bean class="com.kbk.util.InterceptUtil"/>
</mvc:interceptor>
</mvc:interceptors>

运行:



设置之后,职业无法访问,访问自动跳到登录页面



登录后可以成功访问:

===================
===================

1.JWT简单介绍


JWT( JSON Web Token),目的是为了解决跨域认证。JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。通过这个值放在cookie里面


{
"姓名": "张三",
"角色": "管理员",
"到期时间": "2018年7月1日0点0分"

}


以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。



2.拦截器、过滤器、监听器各有什么作用?

拦截器:在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。登录控制,权限管控吧


过滤器:当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。 过滤低俗文字、危险字符等。


监听器:当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。 比如一些联动的操作,比如当注册一个用户的时候自动给他生成一个店铺,或者删除一篇文章之后自动删除它的图片这些。

之前没加监听器,报错,一直找不到原因


三者的作用范围:

参考1: https://blog.csdn.net/c_royi/article/details/80563131

参考2:http://www.r9it.com/20171127/filter-interceptor-lisener.html




3.什么叫明文,什么叫密文,为什么不允许在数据库里明文保存密码?
明文:没用经过加密的数据
密文:经过加密的数据

数据库一旦被盗,安全就丧失。




4.Cookie的失效时间怎么设定?最大允许存放多少字节?


通过cookie.setMaxAge(maxAge);(-1 浏览器关闭即清空,0 失效, 正数 有效时间单位为秒

最大4k,不过看goolge当中的cookie都变成了cookies,都放在一起了。几百KB了




5.在App中没有Cookie,怎么解决用户身份识别的问题?Token应该放在什么位置?怎么在后端设计的时候,又支持Cookie,又支持Token? 


用token.


Token应该放在什么位置?在浏览器中存在cookie中,app中没用cookie,上面说到token就是一个json对象,那就直接放在url后面,HTTP的头部发送
PC端token是存cookie里面的,而app中没有cookie,token是直接保存在app端
所以两者发过请求不一样,一个是cookie,一个是token
服务器端可以采用过滤器(filter校验token,然后采用拦截器(Interceptor)校验 cookie 里的 token
参考token的验证过程:
用户登录校验,校验成功后就返回Token给客户端。
客户端收到数据后保存在客户端
客户端每次访问API是携带Token到服务器端。
服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码



6.什么叫加盐?加盐能解决什么问题?通常的加盐方式有哪些?


加盐:在保存用户密码的时候,加盐可以利用生成的随机数。可以将密码结合MD5加盐,生成的数据摘要和盐保存起来 。以便于下次用户验证使用。在用户表里面,也保存salt。


       我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。加Salt可以一定程度上解决这一问题。


/**
* 加盐MD5
* @param password
* @return
*/
public static String generate(String password) {
Random r = new Random();
StringBuilder sb = new StringBuilder(16);
sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
int len = sb.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sb.append("0");
}
}
String salt = sb.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return new String(cs);

}



7.什么叫MD5,MD5通常做什么用处,为什么MD5不可逆,用做密码加密的时候仍然可能会被解密?


MD5算法是典型的消息摘要算法一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致



MD5不可逆的原因是由于它是一种散列函数(也叫哈希函数,哈希函数又称散列函数,杂凑函数,他是一个单向密码体制,即从明文到密文的不可逆映射,只有加密过程没有解密过程



MD5算法无法防止碰撞(collision),可能被彩虹表破解。

撞库是黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。很多用户在不同网站使用的是相同的帐号密码,因此黑客可以通过获取用户在A网站的账户从而尝试登录B网址,这就可以理解为撞库攻击。



彩虹表(Rainbow Tables)就是一个庞大的、针对各种可能的字母组合预先计算好的哈希值的集合,不一定是针对MD5算法的,各种算法的都有,有了它可以快速的破解各类密码。越是复杂的密码,需要的彩虹表就越大,现在主流的彩虹表都是100G以上。




8.拦截器是什么?为什么要配置拦截器?拦截器里通常应该校验什么,怎么做到统一配置拦截器,让必须登录才能使用的接口,判断用户未登录时,返回错误信息?



Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。
校验cookie,如下列配置:
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,按顺序执行 -->
<mvc:interceptor>
<!--<mvc:mapping path="/**"/> &lt;!&ndash; 拦截所有的url包括子url路径 &ndash;&gt;-->
<mvc:mapping path="/u/**"/><!-- 拦截所有的url包括子url路径 -->
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>
<mvc:exclude-mapping path="/images/**"/>
<bean class="com.kbk.util.InterceptUtil"/>
</mvc:interceptor>
</mvc:interceptors>



9.Https是什么?怎么配置Https证书,哪些请求需要Https,登录是否需要Https? 


超文本传输安全协议(英语:HyperText Transfer Protocol Secure,缩写:HTTPS;常称为HTTP over TLS、HTTP over SSL或HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。



所有隐私数据的传输都应该使用 https,登录也应该使用 https。




10.什么是对称加密,什么是非对称加密?分别适用于什么场景?



对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密

常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES



非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。



公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。


非对称加密的典型应用是数字签名。



常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)



11.Token的构造规则是什么,怎么确认用户身份的,怎么保证Token被偷窃的问题?



这个应该指的是token的数据结构,类似下面:


JWT 的三个部分依次如下。
Header(头部)
Payload(负载)通过这个来校验身份

Signature(签名)


写成一行,就是下面的样子。


Header.Payload.Signature


将JWT 的有效期设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。




12.Cookie是在Http的什么位置存放,Cookie里的键可以重复吗?

在http的头部存放,键可以重复,只要除了value、maxAge之外的参数不完全重复 cookie 就不会被覆盖。




13.什么是session?什么是cookie?session和cookie有什么区别?什么场景适用于session?什么场景适用于cookie?




session:会话,内容存储在服务器上,session id 一般存储在 cookie 里,可以以放在 url 后面。


cookie:服务器给客户端下发的一小段文本,存储在客户端,安全性主要由客户端保证。


session和cookie的区别:


1,session 在服务器端,cookie 在客户端(浏览器)
2,session 默认被存在在服务器的一个文件里(不是内存)
3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
4,session 可以放在 文件、数据库、或内存中都可以。

5,用户验证这种场合一般会用 session 因此,维持一个会话的核心就是客户端的唯一标识,即 session id



应用场景:
将登陆信息等重要信息存放为session。
其他信息如果需要保留,可以放在cookie中。






返回列表 返回列表
评论

    分享到