认证:登录和认证是 两个概念,比如你两周、一个月,可能只登录了一次,但认证却是每次访问都要经过的步骤。
对于图中的认证不成功,也要继续处理,这个我觉得得看业务,比如管理系统,不登录就不让你访问,但对于比如电商的商品信息,不登录,也是可以访问的。
一、写一个用户注册服务
数据库user表:
User类:
单一职责原则:用户注册服务,得新建一个UserInfo类,用来接收前端传过来的注册用户信息,而最好不要使用User类直接接收。
新增方法,可以将UserInfo返回,前端可以做相应的展示。
Controller:
Service:
PostMan调用,成功。
二、HttpBasic认证
在HTTP协议进行通信的过程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份证的方法,当一个客户端向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。
具体做法是,将用户名、密码用:号隔开,然后base64编码,放在请求头的Authorization字段里,值是Basic base64编码的字符串
RequestHeader
Authorization:Basic Base64(用户名:密码)
比较简单,但是安全性不高。
下面写一个HttpBasic过滤器,做认证
package com.nb.security.filter; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.nb.security.entity.User; import com.nb.security.service.IUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.Base64Utils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 处理httpbasic认证过滤器 * httpbasic:请求头,即Authorization:Basic 加密字符串 * 加密字符串为Base64编码的用户名:密码字符串 * Authorization Basic bGh5OmxoeWFwcA== * 在SpringBoot里,任何实现了Filter接口的类,SpringBoot会自动把它加到web应用的过滤器链里,只要声名为Component就行了 */ //@Order(2) @Component public class BasicAuthorizationFilter extends OncePerRequestFilter {//确保在一次请求只通过一次filter,并不是所有的container都像我们期望的只过滤一次,servlet版本不同,表现也不同 @Autowired private IUserService userService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { System.err.println("++++认证++++"); String authHeader = request.getHeader("Authorization"); if (StringUtils.isNotBlank(authHeader)) { String token64 = StringUtils.substringAfter(authHeader, "Basic "); String token = new String(Base64Utils.decodeFromString(token64));//base64解码 String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(token, ":");//分隔用户名和密码 String username = items[0]; String password = items[1]; User user = userService.getOne(new QueryWrapper<User>().eq("username", username)); if (user != null && StringUtils.equals(user.getPassword(), password)) { //将用户信息放到request request.setAttribute("user", user); } } //继续执行其他过滤器 filterChain.doFilter(request, response); } }
Controller:
Postman访问,在请求头输入数据库已存在的username、password:
错误的访问
httpbasic至此完成,问题:不能每个请求都带上用户名密码吧?
+++++++++++++++++++++++++++++分割线++++++++++++++++++++++++++++++
小结
本篇说了 httpbasic过滤器进行HTTPBasic认证
代码:https://github.com/lhy1234/springcloud-security/tree/master/nb-user-api