制作网站过程,企业微网站怎么做,专业团队电影,软件商城官方下载登录功能
基本信息 请求参数 参数格式#xff1a;application/json 请求数据样例#xff1a;
响应数据 参数格式#xff1a;application/json 响应数据样例#xff1a; Slf4j
RestController
public class LoginController {Autowiredpriva…登录功能
基本信息 请求参数 参数格式application/json 请求数据样例
响应数据 参数格式application/json 响应数据样例 Slf4j
RestController
public class LoginController {Autowiredprivate EmpService empService;PostMapping(/login)public Result login(RequestBody Emp emp){log.info(员工登录: {}, emp);Emp e empService.login(emp);//登录失败, 返回错误信息return Result.error(用户名或密码错误);}}Service
public class EmpServiceImpl implements EmpService {Autowiredprivate EmpMapper empMapper;Overridepublic Emp login(Emp emp) {return empMapper.getByUsernameAndPassword(emp);}
}/*** 员工管理*/
Mapper
public interface EmpMapper {/*** 根据用户名和密码查询员工* param emp* return*/Select(select * from emp where username #{username} and password #{password})Emp getByUsernameAndPassword(Emp emp);
}登录校验(重点)
问题分析
在未登录情况下我们也可以直接访问部门管理、员工管理等功能。 所谓登录校验指的是我们在服务器端接收到浏览器发送过来的请求之后首先我们要对请求进行校验。先要校验一下用户登录了没有如果用户已经登录了就直接执行对应的业务操作就可以了如果用户没有登录此时就不允许他执行相关的业务操作直接给前端响应一个错误的结果最终跳转到登录页面要求他登录成功之后再来访问对应的数据。 那应该怎么来实现登录校验的操作呢具体的实现思路可以分为两部分 在员工登录成功后需要将用户登录成功的信息存起来记录用户已经登录成功的 标记。在浏览器发起请求时需要在服务端进行 统一拦截拦截后进行登录校验。 会话技术 会话用户打开浏览器访问 web 服务器的资源会话建立直到有一方断开连接会话结束。在一次会话中可以包含 多次 请求和响应。 会话跟踪一种维护浏览器状态的方法服务器需要识别多次请求是否来自于同一浏览器以便在同一次会话的多次请求间共享数据。 会话跟踪方案 客户端会话跟踪技术Cookie 数据存储在客户端浏览器当中服务端会话跟踪技术Session 数据存储在服务端令牌技术 会话跟踪方案对比 方案一 - Cookie 服务器端在给客户端在响应数据的时候会自动的将 cookie 响应给浏览器浏览器接收到响应回来的 cookie 之后会自动的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中都会将浏览器本地所存储的 cookie 自动地携带到服务端。 为什么这一切都是自动化进行的 是因为 cookie 它是 HTTP 协议当中所支持的技术而各大浏览器厂商都支持了这一标准。在 HTTP协议官方给我们提供了一个响应头和请求头 响应头 Set-Cookie 设置Cookie数据的 请求头 Cookie携带Cookie数据的 /*** Cookie、HttpSession演示*/
Slf4j
RestController
public class SessionController {//设置CookieGetMapping(/c1)public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie(login_username,itheima)); //设置Cookie/响应Cookiereturn Result.success();}//获取CookieGetMapping(/c2)public Result cookie2(HttpServletRequest request){Cookie[] cookies request.getCookies();for (Cookie cookie : cookies) {if(cookie.getName().equals(login_username)){System.out.println(login_username: cookie.getValue()); //输出name为login_username的cookie}}return Result.success();}
}方案二 - Session /*** Cookie、HttpSession演示*/
Slf4j
RestController
public class SessionController {GetMapping(/s1)public Result session1(HttpSession session){log.info(HttpSession-s1: {}, session.hashCode());session.setAttribute(loginUser, tom); //往session中存储数据return Result.success();}GetMapping(/s2)public Result session2(HttpServletRequest request){HttpSession session request.getSession();log.info(HttpSession-s2: {}, session.hashCode());Object loginUser session.getAttribute(loginUser); //从session中获取数据log.info(loginUser: {}, loginUser);return Result.success(loginUser);}
}方案三 - 令牌技术 JWT令牌
前面我们介绍了基于令牌技术来实现会话追踪。这里所提到的令牌就是用户身份的标识其本质就是一个字符串。令牌的形式有很多我们使用的是功能强大的 JWT 令牌。
介绍 全称JSON Web Token https://jwt.io/ 定义了一种简洁的、自包含的格式用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在这些信息是可靠的。 组成 第一部分Header(头 记录令牌类型、签名算法等。 例如{“alg”:“HS256”,“type”:“JWT”}第二部分Payload(有效载荷携带一些自定义信息、默认信息等。 例如{“id”:“1”,“username”:“Tom”}第三部分Signature(签名防止Token被篡改、确保安全性。将header、payload并加入指定秘钥通过指定签名算法计算而来。 Base64是一种基于64个可打印字符A-Z a-z 0-9 /来表示二进制数据的编码方式。 JWT 令牌最典型的应用场景就是 登录认证 在浏览器发起请求来执行登录操作此时会访问登录的接口如果登录成功之后我们需要 生成 一个 jwt 令牌将生成的 jwt 令牌返回给前端。前端拿到 jwt 令牌之后会将 jwt 令牌存储起来。在后续的每一次请求中都会将 jwt 令牌携带到服务端。服务端统一拦截请求之后先来判断一下这次请求有没有把令牌带过来如果没有带过来直接拒绝访问如果带过来了还要 校验 一下令牌是否是有效。如果有效就直接放行进行请求的处理。 JWT令牌的生成和校验 注意事项 JWT 校验时使用的签名秘钥必须和生成 JWT 令牌时使用的秘钥是配套的。如果 JWT 令牌解析校验时报错则说明 JWT 令牌被篡改 或 失效了令牌非法。 !--JWT令牌--dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.1/version/dependency//SpringBootTest
class TliasWebManagementApplicationTests {Testpublic void testUuid(){for (int i 0; i 1000; i) {String uuid UUID.randomUUID().toString();System.out.println(uuid);}}/*** 生成JWT*/Testpublic void testGenJwt(){MapString, Object claims new HashMap();claims.put(id,1);claims.put(name,tom);String jwt Jwts.builder().signWith(SignatureAlgorithm.HS256, itheima)//签名算法.setClaims(claims) //自定义内容(载荷).setExpiration(new Date(System.currentTimeMillis() 3600 * 1000))//设置有效期为1h.compact();System.out.println(jwt);}/*** 解析JWT*/Testpublic void testParseJwt(){Claims claims Jwts.parser().setSigningKey(itheima).parseClaimsJws(eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTY3MDQ2NDU0N30.yPLRyiusrlrmWeC4-dhInjFuAghPkmiHSRHd_DTKi9E).getBody();System.out.println(claims);}
}令牌生成登录成功后生成JWT令牌并返回给前端。 令牌校验在请求到达服务端后对令牌进行统一拦截、校验。 登录下发令牌 用户登录成功后系统会自动下发JWT令牌然后在后续的每次请求中都需要 在请求头header中携带到服务端请求头的名称为 token 值为 登录时下发的 JWT令牌。 如果检测到用户未登录则会返回如下固定错误信息
令牌生成 package com.itheima.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String signKey itheima;private static Long expire 43200000L;/*** 生成JWT令牌* param claims JWT第二部分负载 payload 中存储的内容* return*/public static String generateJwt(MapString, Object claims){String jwt Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() expire)).compact();return jwt;}/*** 解析JWT令牌* param jwt JWT令牌* return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims Jwts.parser().setSigningKey(signKey).parseClaimsJws(jwt).getBody();return claims;}
}package com.itheima.controller;import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;Slf4j
RestController
public class LoginController {Autowiredprivate EmpService empService;PostMapping(/login)public Result login(RequestBody Emp emp){log.info(员工登录: {}, emp);Emp e empService.login(emp);//登录成功,生成令牌,下发令牌if (e ! null){MapString, Object claims new HashMap();claims.put(id, e.getId());claims.put(name, e.getName());claims.put(username, e.getUsername());String jwt JwtUtils.generateJwt(claims); //jwt包含了当前登录的员工信息return Result.success(jwt);}//登录失败, 返回错误信息return Result.error(用户名或密码错误);}}服务器响应的 JWT 令牌存储在本地浏览器哪里了呢 在当前案例中JWT 令牌存储在浏览器的本地存储空间 local storage 中了。 local storage 是浏览器的本地存储在移动端也是支持的。 我们在发起一个查询部门数据的请求此时我们可以看到在请求头中包含一个 token(JWT令牌)后续的每一次请求当中都会将这个令牌携带到服务端。 过滤器Filter
过滤器Filter介绍 概念Filter 过滤器是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。过滤器可以把对资源的请求 拦截 下来从而实现一些特殊的功能。过滤器一般完成一些 通用 的操作比如登录校验、统一编码处理、敏感字符处理等。 Filter 快速入门 步骤 定义过滤器 定义一个类实现 Filter 接口并重写其所有方法。配置过滤器Filter类上加 WebFilter 注解配置拦截资源的路径。引导类上加 ServletComponentScan 开启 Servlet 组件支持。 Filter是是 JavaWeb 三大组件(Servlet、Filter、Listener)之一并不是springboot提供的故需要加上ServletComponentScan 开启 Servlet 组件支持。 package com.itheima.filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;//WebFilter(urlPatterns /*)
public class DemoFilter implements Filter {Override //初始化方法, 只调用一次public void init(FilterConfig filterConfig) throws ServletException {System.out.println(init 初始化方法执行了);}Override //拦截到请求之后调用, 调用多次public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(Demo 拦截到了请求...放行前逻辑);//放行chain.doFilter(request,response);System.out.println(Demo 拦截到了请求...放行后逻辑);}Override //销毁方法, 只调用一次public void destroy() {System.out.println(destroy 销毁方法执行了);}
}package com.itheima;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;ServletComponentScan //开启了对servlet组件的支持
SpringBootApplication
public class TliasWebManagementApplication {public static void main(String[] args) {SpringApplication.run(TliasWebManagementApplication.class, args);}}详解•(执行流程、拦截路径、过滤器链)
执行流程 拦截路径 过滤器链 介绍一个web应用中可以配置多个过滤器这多个过滤器就形成了一个过滤器链。 顺序注解配置的Filter优先级是按照过滤器类名字符串的自然排序。 小结 登录校验-Filter 登录校验Filter-流程 package com.itheima.filter;import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Slf4j
//WebFilter(urlPatterns /*)
public class LoginCheckFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req (HttpServletRequest) request;HttpServletResponse resp (HttpServletResponse) response;//1.获取请求url。String url req.getRequestURL().toString();log.info(请求的url: {},url);//2.判断请求url中是否包含login如果包含说明是登录操作放行。if(url.contains(login)){log.info(登录操作, 放行...);chain.doFilter(request,response);return;}//3.获取请求头中的令牌token。String jwt req.getHeader(token);//4.判断令牌是否存在如果不存在返回错误结果未登录。if(!StringUtils.hasLength(jwt)){log.info(请求头token为空,返回未登录的信息);Result error Result.error(NOT_LOGIN);//手动转换 对象--json -------- 阿里巴巴fastJSONString notLogin JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//5.解析token如果解析失败返回错误结果未登录。try {JwtUtils.parseJWT(jwt);} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info(解析令牌失败, 返回未登录错误信息);Result error Result.error(NOT_LOGIN);//手动转换 对象--json -------- 阿里巴巴fastJSONString notLogin JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//6.放行。log.info(令牌合法, 放行);chain.doFilter(request, response);}
}!--fastJSON--dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.83/version/dependency
拦截器Interceptor
简介 快速入门 概念是一种动态拦截方法调用的机制类似于过滤器。Spring框架中提供的用来动态拦截控制器方法的执行。 作用拦截请求在指定的方法调用前后根据业务需要执行预先设定的代码。 Interceptor 快速入门 步骤 定义拦截器实现 HandlerInterceptor 接口并重写其所有方法。注册拦截器。 详解
拦截器-拦截路径拦截器可以根据需求配置不同的拦截路径
拦截器-执行流程 登录校验- Interceptor 异常处理
程序开发过程中不可避免的会遇到异常现象 package com.itheima.exception;import com.itheima.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理器*/
RestControllerAdvice
public class GlobalExceptionHandler {ExceptionHandler(Exception.class)//捕获所有异常public Result ex(Exception ex){ex.printStackTrace();return Result.error(对不起,操作失败,请联系管理员);}
}上一节
SpringBootWeb案例-2day11-CSDN博客
下一节