本文共 5043 字,大约阅读时间需要 16 分钟。
你未必出类拔萃,但一定与众不同
BASIC认证是从HTTP1.0就定义的一种WEB服务器与通信客户端之间进行的认证方式,又称为基本认证
下图就是对接受到的Authorization字段进行处理,只不过Authorization中存储的是当前请求生成的SessonId进行校验
public class MySessionManager extends DefaultWebSessionManager { /** * 日志记录 */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final String AUTHORIZATION = "Authorization"; private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; public MySessionManager() { super(); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION); //如果请求头中有 Authorization 则其值为sessionId if (!StringUtils.isEmpty(id)) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); return id; } else { //否则按默认规则从cookie取sessionId return super.getSessionId(request, response); } }}
为了弥补BASIC认证的缺点,HTTP在1.1开始就有了DIGEST认证
DIGEST认证同样采用质询/相应的方式,但是不会像BASIC认证认证一样发送明文
一开始一方会先发送认证要求给另一方,接着使用从另一方那接受到的质询码计算生成响应码,最后返回响应码的认证方式。
发送给对方的只是响应摘要以及质询码产生的计算结果,比起BASIC认证,密码泄露的可能性降低了
请求需要认证的资源,服务器会随状态码401Authorization Required,返回带WWW-Authorization首部字段的响应,该字段包含质问响应方式认证所需的临时质询码(随机数)
首部字段WWW-Authorization内必须包含realm和nonce这两个字段的信息,客户端就是依靠向服务器回送这两个值进行认证
接受到401状态码的客户端,返回的响应中包含DIGEST认证必须的首部字段Authorization信息
Authorization必须包含username,realm,nonce,uri,response
接收到包含首部字段Authorization请求的服务器,会先确认认证信息的正确性,认证通过后则返回包含Reques-URI资源的响应。
SSL客户端认证借由HTTPS 的客户端认证起效
HTTPS的认证过程看这篇
基于表单认证,目前市面上大多数都是基于表单认证。
微信小程序发送请求的时候可能不会带入cookie,因此采用表单认证,我们自定义创建一个表单认证
小程序js Authorization存储的就是当前的sessionId,不过这个是我们返回的
// post请求封装export function postRequest(url, data) { var promise = new Promise((resolve, reject) => { var that = this; var postData = data; uni.request({ url: commonUrl + url, data: postData, method: "POST", header: { "content-type": "application/x-www-form-urlencoded", Authorization: uni.getStorageSync("sessionId") }, success: function(res) { //返回什么就相应的做调整 if (res.statusCode == 200) { resolve(res.data); } else { // 请求服务器成功,但是由于服务器没有数据返回,此时无code。会导致这个空数据 //接口后面的then执行 // 不下去,导致报错,所以还是要resolve下,这样起码有个返回值, //不会被阻断在那里执行不下去! resolve(res.data.msg); } }, error: function(e) { reject("网络出错"); } }); }); return promise;}
后端SpringBoot 采用shiro进行校验认证
自定义一个Session管理器,用来对小程序发送的前端Header中的sessionId进行取值
public class MySessionManager extends DefaultWebSessionManager { /** * 日志记录 */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final String AUTHORIZATION = "Authorization"; private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; public MySessionManager() { super(); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION); //如果请求头中有 Authorization 则其值为sessionId if (!StringUtils.isEmpty(id)) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); return id; } else { //否则按默认规则从cookie取sessionId return super.getSessionId(request, response); } }}
在进行第一次登陆的时候
HttpSession session = request.getSession();String sessionId = session.getId();................登陆业务成功以后,返回一个我们生成的sessionIdresultMap.setSessionId(sessionId);
resultMap是我们自定义的一个返回标准类
然后将我们定义的sessionManager注册进去shiro
/** * 自定义sessionManager * @return */@Beanpublic SessionManager sessionManager() { MySessionManager mySessionManager = new MySessionManager(); return mySessionManager;}
转载地址:http://vftzi.baihongyu.com/