首页 文章 精选 留言 我的

精选列表

搜索[PD分离],共10000篇文章
优秀的个人博客,低调大师

Tangdao 2.0.1 发布,更新前后分离,完成基础角色权限,数据权限组件

Tangdao 是基于角色的权限管理系统(RBAC),采用Springboot开发。系统简单易懂,前端使用Vue、Quasarframework开发,页面简洁美观。后端核心框架使用Springboot、Mybatis-plus、SpringSecurity为主要,扩展基于框架的权限校验、参数校验、统一异常、统一响应的通用功能。 预览效果 前端使用: Vue、Quasarframework开发,页面简洁美观 后端使用:Springboot、Mybatis-plus主要框架开发,封装统异常处理,认证,数据权限 前端地址 后端地址 本次更新: 1、项目结构调整,使用优秀的开源工具包,简化项目重复开发量。 2、数据权限组件,简化数据权限开发流程使用注解配置的方式。 其他: 1、前端使用Vue Quasarframework框架,目前看ts写的比较全也比较好的组件框架。 2、开发业务功能如:社区、商品、支付等模块方便快捷。 3、第三方登录对接 4、微信生态小程序等接口对接 注:佛系开发,无任何计划规划。有问题可以 issues 错误问题会修复。 Copyright 2020 ruyangit Inc. Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0

优秀的个人博客,低调大师

前后端分离架构使用shiro框架进行登录的两种实现

方法一:重写FormAuthenticationFilter 原理: 假设在shiro.xml中配置了 /** = authc 而默认authc对应org.apache.shiro.web.filter.authc.FormAuthenticationFilter过滤器 则表示所有路径都被此过滤器拦截 当未登录请求被拦截,会调用FormAuthenticationFilter.onAccessDeny(): 如果请求的是loginUrl,则调用AuthenticatingFilter.executeLogin() 如果不是,则使request重定向到loginUrl,并return false; AuthenticatingFilter.executeLogin(): 调用subject.login(token) 如果登录成功,则调用onLoginSuccess() 失败则调用onLoginFailure() AuthenticatingFilter.onLoginSuccess(): return true; AuthenticatingFilter.onLoginFailure(): return false; subject.login(token): 最终会调用realm的doGetAuthenticationInfo 思路 重写默认的FormAuthenticationFilter, 在onAccessDeny()方法中: 如果请求的是loginUrl,则调用AuthenticatingFilter.executeLogin() 如果不是,则返回json,提示“未登录,无法访问该地址” @Override protectedbooleanonAccessDenied(ServletRequestrequest,ServletResponseresponse)throwsException{ if(this.isLoginRequest(request,response)){ if(this.isLoginSubmission(request,response)){ if(log.isTraceEnabled()){ log.trace("Loginsubmissiondetected.Attemptingtoexecutelogin."); } returnthis.executeLogin(request,response); }else{ if(log.isTraceEnabled()){ log.trace("Loginpageview."); } returntrue; } }else{ if(log.isTraceEnabled()){ log.trace("Attemptingtoaccessapathwhichrequiresauthentication.ForwardingtotheAuthenticationurl["+this.getLoginUrl()+"]"); } response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriterout=response.getWriter(); ServerResponseserverResponse=ServerResponse.createByErrorMessage("未登录,无法访问该地址"); Gsongson=GsonFactory.getGson(); Strings=gson.toJson(serverResponse); out.println(s); out.flush(); out.close(); returnfalse; } } 由于AuthenticatingFilter.executeLogin()会调用onLoginSuccess()和onLoginFailure()方法 所以我们重写两个方法,前者返回登录成功的json,并把当前用户放入session;后者返回登录失败的json @Override protectedbooleanonLoginSuccess(AuthenticationTokentoken,Subjectsubject,ServletRequestrequest,ServletResponseresponse)throwsException{ response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriterout=null; try{ out=response.getWriter(); }catch(IOExceptione1){ e1.printStackTrace(); } HttpSessionsession=((HttpServletRequest)request).getSession(); Useruser=userMapper.selectByUserName(token.getPrincipal().toString()); session.setAttribute(Const.CURRENT_USER,user); ServerResponseserverResponse=ServerResponse.createBySuccessMsg("登录成功"); Gsongson=GsonFactory.getGson(); Strings=gson.toJson(serverResponse); out.println(s); out.flush(); out.close(); returntrue; } @Override protectedbooleanonLoginFailure(AuthenticationTokentoken,AuthenticationExceptione,ServletRequestrequest,ServletResponseresponse){ response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriterout=null; try{ out=response.getWriter(); }catch(IOExceptione1){ e1.printStackTrace(); } ServerResponseserverResponse=ServerResponse.createByErrorMessage("登录失败"); Gsongson=GsonFactory.getGson(); Strings=gson.toJson(serverResponse); out.println(s); out.flush(); out.close(); returnfalse; } } 最后配置shiro.xml将authc对应的默认的FormAuthenticationFilter,替换成我们的MyAuthenticationFilter <beanid="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <propertyname="securityManager"ref="securityManager"/> <propertyname="loginUrl"value="/user/login.do"/> <propertyname="unauthorizedUrl"value="/user/unauthorized_err"/> <propertyname="filters"> <map> <entrykey="authc"value-ref="myAuthenticationFilter"/> </map> </property> <propertyname="filterChainDefinitions"> <value> /user/login_err.do=anon /user/unauthorized_err.do=anon /**=authc </value> </property> </bean> <beanid="myAuthenticationFilter"class="com.mmall.shiro.filter.MyAuthenticationFilter"/> 方法二:使用PassThruAuthenticationFilter代替FormAuthenticationFilter 原理: org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter源码: publicclassPassThruAuthenticationFilterextendsAuthenticationFilter{ publicPassThruAuthenticationFilter(){ } protectedbooleanonAccessDenied(ServletRequestrequest,ServletResponseresponse)throwsException{ if(this.isLoginRequest(request,response)){ returntrue; }else{ this.saveRequestAndRedirectToLogin(request,response); returnfalse; } } } 官方文档: An authentication filter that redirects the user to the login page when they are trying to access a protected resource. However, if the user is trying to access the login page, the filter lets the request pass through to the application code. The difference between this filter and the FormAuthenticationFilter is that on a login submission (by default an HTTP POST to the login URL), the FormAuthenticationFilter filter attempts to automatically authenticate the user by passing the username and password request parameter values to Subject.login(usernamePasswordToken) directly. Conversely, this controller always passes all requests to the loginUrl through, both GETs and POSTs. This is useful in cases where the developer wants to write their own login behavior, which should include a call to Subject.login(AuthenticationToken) at some point. For example, if the developer has their own custom MVC login controller or validator, this PassThruAuthenticationFilter may be appropriate. 我们继承PassThruAuthenticationFilter并重写onAccessDenied方法,和redirectToLogin方法 publicclassMyPassThruAuthenticationFilterextendsPassThruAuthenticationFilter{ privateStringloginErrUrl="/"; publicvoidsetLoginErrUrl(StringloginErrUrl){ this.loginErrUrl=loginErrUrl; } @Override protectedbooleanonAccessDenied(ServletRequestrequest,ServletResponseresponse)throwsException{ if(this.isLoginRequest(request,response)){ returntrue; }else{ this.saveRequestAndRedirectToLogin(request,response); returnfalse; } } //重写redirectToLogin方法是因为saveRequestAndRedirectToLogin方法会调用它,而原始的redirectToLogin方法会使得请求重定向到loginUrl @Override protectedvoidredirectToLogin(ServletRequestrequest,ServletResponseresponse)throwsIOException{ WebUtils.issueRedirect(request,response,loginErrUrl); } } 首先修改shiro.xml , 将authc默认对应的FormAuthenticationFilter修改为MyPassThruAuthenticationFilter <beanid="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <propertyname="securityManager"ref="securityManager"/> <propertyname="loginUrl"value="/user/login.do"/> <propertyname="unauthorizedUrl"value="/user/unauthorized_err"/> <propertyname="filters"> <map> <entrykey="authc"> <beanclass="com.mmall.shiro.filter.MyPassThruAuthenticationFilter"> <propertyname="loginErrUrl"value="/user/login_err.do"/><!--注意这里的loginErrUrl与上面的loginUrl的区别--> </bean> </entry> </map> </property> <propertyname="filterChainDefinitions"> <value> /=anon /user/login_err.do=anon /user/unauthorized_err.do=anon /user/logout.do=logout /**=authc </value> </property> </bean> 然后修改loginUrl对应的Contoller的方法,在其中要调用subject.login()完成shiro的认证 //UserController中:结合shiro,使用PassThruAuthenticationFilter的登录,需要调用subject.login()完成shiro的认证 @RequestMapping(value="login.do",method=RequestMethod.POST) @ResponseBody publicServerResponselogin(@RequestBodyUseruser,HttpSessionsession){ Subjectsubject=SecurityUtils.getSubject(); UsernamePasswordTokentoken=newUsernamePasswordToken(user.getUsername(),user.getPassword()); //ServerResponseserverResponse=iUserService.login(user.getUsername(),user.getPassword()); try{ /**subject.login(token)提交申请,验证能不能通过,也就是交给shiro。这里会回调reaml(或自定义的realm)里的一个方法 protectedAuthenticationInfodoGetAuthenticationInfo()*/ subject.login(token); }catch(AuthenticationExceptione){//验证身份失败 returnServerResponse.createByErrorMessage("登陆客户身份失败!"); } /**Shiro验证后,跳转到此处,这里判断验证是否通过*/ if(subject.isAuthenticated()){//验证身份通过 session.setAttribute(Const.CURRENT_USER,subject.getPrincipal()); returnServerResponse.createBySuccessMsg("登录成功"); }else{ returnServerResponse.createByErrorMessage("登陆客户身份失败!"); } } 而loginErrUrl对应的方法则返回Json提示未登录: @RequestMapping(value="login_err.do",method=RequestMethod.GET) @ResponseBody publicServerResponselogin_error(){ returnServerResponse.createByErrorMessage("用户未登录"); }

优秀的个人博客,低调大师

阿里云HybridDB for PG 空间紧张的解法 - 冷热分离、空间锁定、分区、压缩

标签 PostgreSQL , Greenplum , HybridDB for PG 背景 数据库空间不够用怎么办? HDB PG是分布式数据库,空间不够用,扩容呗。但是用户如果不想扩容呢?还有哪些处理方法? 例子 1 查看当前已使用空间 查看数据库空间使用,表的空间使用,索引的空间使用等。 postgres=# select datname,pg_size_pretty(pg_database_size(datname)) from pg_database order by pg_database_size(datname) desc; datname | pg_size_pretty -----------+---------------- postgres | 32 MB template1 | 31 MB template

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册