当前位置: 首页 > news >正文

天津做网站的广州建设网站专家

天津做网站的,广州建设网站专家,小型网站商城建设,上海倒闭工厂名单背景 我们在基于Session做登录认证的时候#xff0c;会有一些问题#xff0c;因为Session存储到服务器端#xff0c;然后通过客户端的Cookie进行匹配#xff0c;如果正确#xff0c;则通过认证#xff0c;否则不通过认证。这在简单的系统中可以这么使用#xff0c;并且…背景 我们在基于Session做登录认证的时候会有一些问题因为Session存储到服务器端然后通过客户端的Cookie进行匹配如果正确则通过认证否则不通过认证。这在简单的系统中可以这么使用并且难度是最低的但是如果在大型分布式项目中如果还是基于Session做登录认证的话就不可行了。这个时候我们可以基于token做登录认证。token其实就是一个字符串生成token的实现方案有很多种可以使用uuid作为token也可以使用jwt作为token其中使用jwt实现的方案是最流行的那么下面将会讲如何在SpringBoot中基于jwt实现token登录认证。 1. 引入依赖 dependencygroupIdcom.auth0/groupIdartifactIdjava-jwt/artifactIdversion4.4.0/version /dependency2. 自定义注解 自定义一个注解在需要认证的方法上添加该注解 Target({ElementType.METHOD,ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface Auth {boolean require() default true; }3. 编写拦截器 通过识别是否在接口上添加Auth注解来确定是否需要登录才能访问。 同时这里需要注意只拦截HandlerMethod类型同时还要考虑放行BasicErrorController因为基本的报错在这个控制器中如果不放行那么会看不到报错信息。 public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod (HandlerMethod) handler;if (handlerMethod.getBean() instanceof BasicErrorController) {return true;}Auth auth handlerMethod.getMethod().getAnnotation(Auth.class);if (auth ! null auth.require()) {String token request.getHeader(token);if (StringUtils.isNotBlank(token)) {if (TokenUtil.verifyToken(token)) { // 校验 token 是否正确return true;} else {request.getRequestDispatcher(/error/tokenError).forward(request, response); // 这里你也可以直接抛出自定义异常然后在全局异常处理器中处理}} else {request.getRequestDispatcher(/error/token).forward(request, response); // 这里你也可以直接抛出自定义异常然后在全局异常处理器中处理}} else {return true;}} else {return true;}return false;} }4. 定义跨域拦截器 这里是做前后端分离需要做的步骤解决跨域的方式有好几种这里使用拦截器的方式解决跨域问题。 public class CrossInterceptorHandler implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {response.setHeader(Access-Control-Allow-Origin, *);response.setHeader(Access-Control-Allow-Credentials, true);response.setHeader(Access-Control-Allow-Methods, POST, GET , PUT , OPTIONS);response.setHeader(Access-Control-Max-Age, 3600);response.setHeader(Access-Control-Allow-Headers, x-requested-with,accept,authorization,content-type);return true;} }5. 定义全局异常处理器 这里没有用到全局异常处理器不过为了项目的完整性我还是选择把这些常规的内容写上去。 RestControllerAdvice public class GlobalException {public final Logger logger LoggerFactory.getLogger(this.getClass());ExceptionHandler(TokenExpiredException.class)public R? handleTokenExpiredException(TokenExpiredException e) {logger.error(token 已过期);logger.error(e.getMessage());return R.error(ResponseEnum.TOKEN_EX);} }6. 定义工具类 6.1 统一错误状态码 编写一个枚举类统一项目的报错状态码。 AllArgsConstructor Getter public enum ResponseEnum {SUCCESS(200, 操作成功),FAIL(300,获取数据失败),USER_EX(301,用户不存在请重新登录),ERROR(302,错误请求),USERNAME_PASSWORD_ERROR(303,用户名或密码错误),NO_TOKEN(400,无token请重新登录),TOKEN_VERIFY_ERROR(401,token验证失败请重新登录),TOKEN_EX(402,token已过期);private final Integer code;private final String msg;public static ResponseEnum getResultCode(Integer code){for (ResponseEnum value : ResponseEnum.values()) {if (code.equals(value.getCode())){return value;}}return ResponseEnum.ERROR;} }6.2 统一响应类 Data public class RT implements Serializable {private static final long serialVersionUID 56665257244236049L;private Integer code;private String message;private T data;private R() {}public static T RT ok(T data) {RT response new R();response.setCode(ResponseEnum.SUCCESS.getCode());response.setMessage(ResponseEnum.SUCCESS.getMsg());response.setData(data);return response;}public static T RT error(Integer errCode, String errMessage) {RT response new R();response.setCode(errCode);response.setMessage(errMessage);return response;}public static T RT error(ResponseEnum responseEnum) {RT response new R();response.setCode(responseEnum.getCode());response.setMessage(responseEnum.getMsg());return response;} }6.3 Token工具类 通过TokenUtil可以生成token和验证token是否正确。 import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;/*** author Luke Ewin* date 2024/2/19 16:59* blog blog.lukeewin.top*/ public class TokenUtil {private final static String ENCRYPT_KEY abc123; // 加密的密钥private final static int EXPIRE_TIME 1; // token 过期时间单位分钟private static final String ISSUER zhangsan;/*** 生成 token** param json 要封装到 token 的内容如果要传递多个参数内容可以定义为 JSON 或者 Map* return 返回 token*/public static String createToken(JSONObject json) {return JWT.create().withSubject(json.toString()) // 不要把密码封装进去不安全.withIssuer(ISSUER) // 设置发布者.withExpiresAt(DateUtil.offsetMinute(new Date(), EXPIRE_TIME)) // 设置过期时间.withClaim(test, 123) // 这里是随便设置的内容类似 Map.sign(Algorithm.HMAC256(ENCRYPT_KEY)); // 加密}/*** 验证 token** param token* return*/public static boolean verifyToken(String token) {try {JWTVerifier jwtVerifier JWT.require(Algorithm.HMAC256(ENCRYPT_KEY)).withIssuer(ISSUER).build();jwtVerifier.verify(token);return true;} catch (Exception e) { // 如果 token 过期会报错 TokenExpiredExceptione.printStackTrace();return false;}} }7. 编写实体类 这里为了简单并没有与数据库交互。 Data public class User {private String userName;private String password;private String token; }8. 定义控制器 8.1 定义登录控制器类 RestController RequestMapping(/user) public class LoginController {PostMapping(/login)public RUser login(String userName, String password) {if (StringUtils.isNotBlank(userName) StringUtils.isNotBlank(password)) {if (张三.equals(userName) 123456.equals(password)) {User user new User();JSONObject json JSONUtil.createObj().put(name, zhangsan);String token TokenUtil.createToken(json);user.setToken(token);return R.ok(user);}}return R.error(ResponseEnum.USERNAME_PASSWORD_ERROR);} }8.2 定义报错处理器 RestController RequestMapping(/error) public class ErrorController {PostMapping(/token)public R? token() {return R.error(ResponseEnum.NO_TOKEN);}PostMapping(/tokenError)public R? tokenError() {return R.error(ResponseEnum.TOKEN_VERIFY_ERROR);} }8.3 定义测试控制器 RestController RequestMapping(/test) public class TestController {AuthPostMapping(/hello)public R? hello() {return R.ok(登录成功);}PostMapping(/hi)public R? hi() {return R.ok(登录成功);} }9. 配置类 最后别忘了定义一个配置类把我们自定义的两个拦截器注册进去。 Configuration public class WebMvcConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new CrossInterceptorHandler()).addPathPatterns(new String[] {/**});registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/**).excludePathPatterns(/user/login, /error/**);} }10. 最终的效果 访问登录接口通过提交表单方式提交请求通过token验证后会返回一个token然后我们请求添加了Auth注解的接口都需要在请求头添加token字段和对应的值。 如果请求头中没有填写token或者填写的不对在请求需求登录后才能访问的接口时都会报错。比如这里的/test/hello是需要登录后才能访问的接口如果没有正确填写token那么会报错如下图所示。 如果正确填写了token那么效果如下。 有一个test/hi接口没有Auth注解可以不用登录就能访问如下图所示。 以上就是本篇文章所分享的内容如果对你有用记得收藏哦 更多Java干货欢迎关注我的博客。 代码已经开源到github中如需要下载源代码可点击这里。
http://www.hkea.cn/news/14319347/

相关文章:

  • 佛山市和城乡建设局网站首页中国纪检监察报社长范清安
  • 古装衣服店网站建设页面wordpress 乱版
  • dw做网站首页长宽设置多少wordpress个人博客前台模板
  • 太和网站开发招聘达州市建设规划网站
  • 建设网站书籍马鞍山网站建设价格
  • 医院诊所网站源码开发公司资质等级
  • 深圳做网站补贴北京网站建设哪家公司好
  • 怎么样的网站合适做城市代理合肥关键词排名首页
  • wix建设网站网站建设大学
  • 宁波网站建设详细内容路由器做网站主机要备案吗
  • 青海省建设厅官方网站一个网站 二级域名
  • 印刷 网站模板佛山网站建设seo优化
  • 宜城网站开发85同城找工作招聘
  • 上海企业网站建站国际外贸平台排名
  • 佛山商城网站制作一个空间怎么放多个网站吗
  • 银川免费网站建设贵州省建设厅的网站首页
  • 一流的网站建设哪家好化工网站关键词优化
  • 财政网站平台建设不足麻章手机网站建设公司
  • 建站软件2017建网站没有实体公司能建站吗
  • 三网合一网站怎么做学校建设网站费用申请
  • 益阳北京网站建设wordpress源码整站
  • 烟台网站建设推荐企汇互联见效付款个人网站建设费用
  • 广州番禺网站建设工作室沈阳流产手术哪家比较好
  • 大连哪里有手机自适应网站建设维护软件公司起名大全
  • 网络服务是干什么的优化网络
  • 法国网站域名云南省建设厅专家注册网站
  • dede5.7网站搬家全包装修包括哪些项目
  • vi设计网站排行榜wordpress仿站教程2018
  • 做网站搞流量挂联盟广告变现手机如何做api网站
  • 医药网站建设价格怎么验证网站备案密码是否正确