• 登录认证,登录校验


    一、基础登录功能

     1.Controller层

    1. import com.itheima.pojo.Emp;
    2. import com.itheima.pojo.Result;
    3. import com.itheima.service.EmpService;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.web.bind.annotation.PostMapping;
    7. import org.springframework.web.bind.annotation.RequestBody;
    8. import org.springframework.web.bind.annotation.RestController;
    9. @Slf4j
    10. @RestController
    11. public class LoginController {
    12. @Autowired
    13. private EmpService empService;
    14. @PostMapping("/login")
    15. public Result login(@RequestBody Emp emp){
    16. log.info ( "登录用户名:{},密码:{}",emp );
    17. Emp e =empService.login(emp);
    18. return e!=null?Result.success ():Result.error ( "用户名或密码错误" );
    19. }
    20. }

    2.Service层

    1. @Override
    2. public Emp login(Emp emp) {
    3. return empMapper.getByusernameAndPassword(emp);
    4. }
    5. }

    3.Mapper层

    1. /**
    2. * 根据用户名密码查询员工
    3. * @param emp
    4. * @return
    5. */
    6. @Select ( "select * from emp where username=#{username} and password=#{password}")
    7. Emp getByusernameAndPassword(Emp emp);

    二、登录校验

    1.会话技术

    1.会话跟踪方案对比

    1. import com.itheima.pojo.Result;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.web.bind.annotation.GetMapping;
    4. import org.springframework.web.bind.annotation.RestController;
    5. import javax.servlet.http.Cookie;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. import javax.servlet.http.HttpSession;
    9. /**
    10. * HttpSession演示
    11. */
    12. @Slf4j
    13. @RestController
    14. public class SessionController {
    15. //设置Cookie
    16. @GetMapping("/c1")
    17. public Result cookie1(HttpServletResponse response){
    18. response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie
    19. return Result.success();
    20. }
    21. //获取Cookie
    22. @GetMapping("/c2")
    23. public Result cookie2(HttpServletRequest request){
    24. Cookie[] cookies = request.getCookies();
    25. for (Cookie cookie : cookies) {
    26. if(cookie.getName().equals("login_username")){
    27. System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie
    28. }
    29. }
    30. return Result.success();
    31. }
    32. @GetMapping("/s1")
    33. public Result session1(HttpSession session){
    34. log.info("HttpSession-s1: {}", session.hashCode());
    35. session.setAttribute("loginUser", "tom"); //往session中存储数据
    36. return Result.success();
    37. }
    38. @GetMapping("/s2")
    39. public Result session2(HttpServletRequest request){
    40. HttpSession session = request.getSession();
    41. log.info("HttpSession-s2: {}", session.hashCode());
    42. Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
    43. log.info("loginUser: {}", loginUser);
    44. return Result.success(loginUser);
    45. }
    46. }

    2.JWT令牌技术

    1. /**
    2. * 测试Jwt令牌的生成
    3. */
    4. @Test
    5. public void testGenJwt(){
    6. Map claims=new HashMap<> ();
    7. claims.put ( "id",1 );
    8. claims.put ( "name","TOM" );
    9. String jwt = Jwts.builder ()
    10. .signWith ( SignatureAlgorithm.HS256, "itheima" )//签名算法
    11. .setClaims ( claims )//自定义内容(载荷)
    12. .setExpiration ( new Date ( System.currentTimeMillis () ) )
    13. // .setExpiration ( new Date ( System.currentTimeMillis () + 3600 * 1000 ) )//设置令牌的有效期为1个小时
    14. .compact ();//返回一个jwt令牌
    15. System.out.println (jwt);
    16. }

    1.生成JWT令牌

    2.令牌解析

    1. @Test
    2. public void testPrasejwt(){
    3. Claims claims = Jwts.parser ()
    4. .setSigningKey ( "itheima" )
    5. .parseClaimsJws ( "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVE9NIiwiaWQiOjEsImV4cCI6MTY5NzAwOTgwN30.9iduxbB4vpQLGs3anczG-spuQdT5f_3BR6aHYYHop3M" )
    6. .getBody ();
    7. System.out.println ( claims );
    8. }

    3.登陆后下发令牌

    1.jwtUtils类
    1. import io.jsonwebtoken.Claims;
    2. import io.jsonwebtoken.Jwts;
    3. import io.jsonwebtoken.SignatureAlgorithm;
    4. import java.util.Date;
    5. import java.util.Map;
    6. public class JwtUtils {
    7. private static String signKey = "itheima";
    8. private static Long expire = 43200000L;
    9. /**
    10. * 生成JWT令牌
    11. * @param claims JWT第二部分负载 payload 中存储的内容
    12. * @return
    13. */
    14. public static String generateJwt(Map claims){
    15. String jwt = Jwts.builder()
    16. .addClaims(claims)
    17. .signWith(SignatureAlgorithm.HS256, signKey)
    18. .setExpiration(new Date(System.currentTimeMillis() + expire))
    19. .compact();
    20. return jwt;
    21. }
    22. /**
    23. * 解析JWT令牌
    24. * @param jwt JWT令牌
    25. * @return JWT第二部分负载 payload 中存储的内容
    26. */
    27. public static Claims parseJWT(String jwt){
    28. Claims claims = Jwts.parser()
    29. .setSigningKey(signKey)
    30. .parseClaimsJws(jwt)
    31. .getBody();
    32. return claims;
    33. }
    34. }
    2.Controller层
    1. import com.itheima.pojo.Emp;
    2. import com.itheima.pojo.Result;
    3. import com.itheima.service.EmpService;
    4. import com.itheima.utils.JwtUtils;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.PostMapping;
    8. import org.springframework.web.bind.annotation.RequestBody;
    9. import org.springframework.web.bind.annotation.RestController;
    10. import java.util.HashMap;
    11. import java.util.Map;
    12. @Slf4j
    13. @RestController
    14. public class LoginController {
    15. @Autowired
    16. private EmpService empService;
    17. @PostMapping("/login")
    18. public Result login(@RequestBody Emp emp){
    19. log.info ( "登录用户名:{},密码:{}",emp );
    20. Emp e =empService.login(emp);
    21. //登陆成功,生成令牌,下发令牌
    22. if (e!=null){
    23. Map claims=new HashMap<> ();
    24. claims.put ( "id",e.getId () );
    25. claims.put ( "name",e.getUsername () );
    26. claims.put ( "username",e.getUsername () );
    27. String jwt = JwtUtils.generateJwt ( claims );//jwt 包含了当前登录的员工信息
    28. return Result.success (jwt);//下发jwt令牌
    29. }
    30. //登录失败,返回错误信息
    31. return Result.error ( "用户名或密码错误" );
    32. }
    33. }

    三、过滤器 -Filter

    1.入门程序

    1. import javax.servlet.*;
    2. import javax.servlet.annotation.WebFilter;
    3. import java.io.IOException;
    4. @WebFilter(urlPatterns = "/*")
    5. public class DemoFilter implements Filter {
    6. @Override //初始化方法只调用一次
    7. public void init(FilterConfig filterConfig) throws ServletException {
    8. System.out.println ("初始化方法被调用了");
    9. }
    10. @Override //拦截到请求之后调用
    11. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
    12. System.out.println ("拦截到了请求");
    13. chain.doFilter ( servletRequest,servletResponse );//放行
    14. }
    15. @Override //销毁方法,只调用一次
    16. public void destroy() {
    17. System.out.println ("销毁方法被调用了");
    18. }
    19. }

    2.Filter详解

    1.Filter执行流程

    2.过滤器的拦截路径

    3.过滤器链

    3.Filter完成登录校验

    1.LoginCheckFilter

    1. import com.alibaba.fastjson.JSONObject;
    2. import com.itheima.pojo.Result;
    3. import com.itheima.utils.JwtUtils;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.springframework.util.StringUtils;
    6. import javax.servlet.*;
    7. import javax.servlet.annotation.WebFilter;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import java.io.IOException;
    11. @Slf4j
    12. @WebFilter(urlPatterns = "/*")
    13. public class LoginCheckFilter implements Filter {
    14. @Override
    15. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    16. HttpServletRequest req = (HttpServletRequest) servletRequest;
    17. HttpServletResponse resp = (HttpServletResponse) servletResponse;
    18. //1.获取请求url
    19. String url = req.getRequestURI ().toString ();
    20. log.info ( "请求的url:{}",url );
    21. //2.判断请求url中是否包含login,如果包含,说明是登陆操作,放行
    22. if (url.contains ( "login" )){
    23. log.info ("登陆操作,放行...");
    24. filterChain.doFilter (servletRequest,servletResponse );
    25. return;
    26. }
    27. //3.获取请求头的令牌(token)
    28. String jwt = req.getHeader ( "token" );
    29. //4.判断令牌是否存在,如果不存在,返错误结果(未登录)
    30. if (!StringUtils.hasLength ( jwt )){
    31. log.info ( "请求头token为空,返回未登录的信息" );
    32. Result error = Result.error ( "NOT_LOGIN" );
    33. //手动转换Josn数据
    34. String notLogin = JSONObject.toJSONString ( error );
    35. resp.getWriter ().write ( notLogin );
    36. return;
    37. }
    38. //5.解析token,如果解析失败,返回错误结果(未登录)
    39. try {
    40. JwtUtils.parseJWT ( jwt );
    41. } catch (Exception e) {
    42. e.printStackTrace ();
    43. log.info ( "解析令牌失败,返回未登录错误信息" );
    44. Result error = Result.error ( "NOT_LOGIN" );
    45. //手动转换Josn数据
    46. String notLogin = JSONObject.toJSONString ( error );
    47. resp.getWriter ().write ( notLogin );
    48. return;
    49. }
    50. //6.放行
    51. log.info ( "令牌合法,放行" );
    52. filterChain.doFilter ( servletRequest,servletResponse );
    53. }
    54. }

    2.手动将字符串转换为JSON格式数据

    1. //手动转换Josn数据
    2. String notLogin = JSONObject.toJSONString ( error );
    3. resp.getWriter ().write ( notLogin );

    3.引入依赖

    1. <dependency>
    2. <groupId>com.alibabagroupId>
    3. <artifactId>fastjsonartifactId>
    4. <version>2.0.32version>
    5. dependency>

    四、拦截器

    1.拦截器的基本使用

    1.定义拦截器

    1. import org.springframework.stereotype.Component;
    2. import org.springframework.web.servlet.HandlerInterceptor;
    3. import org.springframework.web.servlet.ModelAndView;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. @Component
    7. public class LoginCheckInterceptor implements HandlerInterceptor {
    8. @Override//目标资源方法运行前运行,返回true 放行
    9. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    10. System.out.println ("preHandle...");
    11. return true;
    12. }
    13. @Override//目标资源方法运行后运行
    14. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    15. System.out.println ("postHandle.....");
    16. }
    17. @Override//视图渲染完毕后,最后运行
    18. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    19. System.out.println ("afterCompletion...");
    20. }
    21. }

    2.配置拦截器

    1. import com.itheima.interceptor.LoginCheckInterceptor;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    6. @Configuration//配置类
    7. public class WebConfig implements WebMvcConfigurer {
    8. @Autowired
    9. private LoginCheckInterceptor loginCheckInterceptor;
    10. @Override
    11. public void addInterceptors(InterceptorRegistry registry) {
    12. registry.addInterceptor ( loginCheckInterceptor ).addPathPatterns ( "/**" );
    13. }
    14. }

    2.拦截路径,执行流程

     3.拦截器完成登录校验

    1. import com.alibaba.fastjson.JSONObject;
    2. import com.itheima.pojo.Result;
    3. import com.itheima.utils.JwtUtils;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.springframework.util.StringUtils;
    6. import javax.servlet.*;
    7. import javax.servlet.annotation.WebFilter;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import java.io.IOException;
    11. @Slf4j
    12. //@WebFilter(urlPatterns = "/*")
    13. public class LoginCheckFilter implements Filter {
    14. @Override
    15. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    16. HttpServletRequest req = (HttpServletRequest) servletRequest;
    17. HttpServletResponse resp = (HttpServletResponse) servletResponse;
    18. //1.获取请求url
    19. String url = req.getRequestURI ().toString ();
    20. log.info ( "请求的url:{}",url );
    21. //2.判断请求url中是否包含login,如果包含,说明是登陆操作,放行
    22. if (url.contains ( "login" )){
    23. log.info ("登陆操作,放行...");
    24. filterChain.doFilter (servletRequest,servletResponse );
    25. return;
    26. }
    27. //3.获取请求头的令牌(token)
    28. String jwt = req.getHeader ( "token" );
    29. //4.判断令牌是否存在,如果不存在,返错误结果(未登录)
    30. if (!StringUtils.hasLength ( jwt )){
    31. log.info ( "请求头token为空,返回未登录的信息" );
    32. Result error = Result.error ( "NOT_LOGIN" );
    33. //手动转换Josn数据
    34. String notLogin = JSONObject.toJSONString ( error );
    35. resp.getWriter ().write ( notLogin );
    36. return;
    37. }
    38. //5.解析token,如果解析失败,返回错误结果(未登录)
    39. try {
    40. JwtUtils.parseJWT ( jwt );
    41. } catch (Exception e) {
    42. e.printStackTrace ();
    43. log.info ( "解析令牌失败,返回未登录错误信息" );
    44. Result error = Result.error ( "NOT_LOGIN" );
    45. //手动转换Josn数据
    46. String notLogin = JSONObject.toJSONString ( error );
    47. resp.getWriter ().write ( notLogin );
    48. return;
    49. }
    50. //6.放行
    51. log.info ( "令牌合法,放行" );
    52. filterChain.doFilter ( servletRequest,servletResponse );
    53. }
    54. }

    五、异常处理

    1. import com.itheima.pojo.Result;
    2. import org.springframework.web.bind.annotation.ExceptionHandler;
    3. import org.springframework.web.bind.annotation.RestControllerAdvice;
    4. /**
    5. * 全局异常处理器
    6. */
    7. @RestControllerAdvice
    8. public class GlobalExceptionHandler {
    9. @ExceptionHandler(Exception.class)//捕获异常的类型
    10. public Result ex(Exception exception){
    11. return Result.error ( "对不起操作失败,请联系管理员" );
    12. }
    13. }

  • 相关阅读:
    考研数一和数二不一样的知识章节汇总
    不定积分(原函数)存在性定理、定积分存在性定理、变限积分存在性定理
    用 Pytest+Allure 生成漂亮的 HTML 图形化测试报告
    杰理之内置关机电流 1.2uA,之后不能长按开机【篇】
    STM32CUBEMX_创建时间片轮询架构的软件框架
    登录业务实现(单点登录+微信扫码+短信服务)
    哪些人需要考PMP®证书呢?考了PMP®证书有什么用呢?
    JVM学习——类的加载器以及类的加载过程
    Go:Bitwise按位算法(附完整源码)
    【深度学习3】线性回归与逻辑回归
  • 原文地址:https://blog.csdn.net/m0_64703222/article/details/133766996