凉衫薄

人生哪能多如意,万事只求半称心。
最新文章
问题 在前后端未分离的架构中,一般由shiro认证后,直接返回登陆成功的视图。而在前后端分离的架构中,页面的跳转由前端路由控制,后端仅仅返回json数据给前端。要在前后端分离架构中使用shiro就必须将返回视图的逻辑改为返回json。 Shiro过滤器的拦截过程 我们先来看一下Shiro过滤器的继承关系,如下图所示(图片偷来的): 我们需要关注的是AccessControlFilter这个过滤器,AccessControlFilter中有三个比较常用的方法: protected abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception; protected abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception; public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception; 1.isAccessAllowed方法表示该URL是否允许访问,mappedValue参数是我们配置的URL拦截规则,返回true表示允许访问,false表示不允许访问。 2.onAccessDenied方法表示当请求被拒绝时,是否需要继续处理,返回true表示继续处理,返回false表示不再执行拦截器链,直接返回。 3.onPrehandle方法是AdviceFilter方法中定义的,他会调用isAccessAllowed和onAccessDenied来判断是否进行处理,源码如下: public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue); } 而我们在前后端未分离架构中常用的是AccessControlFilter的子类FormAuthenticationFilter,他的onAccessDenied是这样写的: protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { if (isLoginRequest(request, response)) { if (isLoginSubmission(request, response)) { if (log.isTraceEnabled()) { log.trace("Login submission detected. Attempting to execute login."); } return executeLogin(request, response); } else { if (log.isTraceEnabled()) { log.trace("Login page view."); } //allow them to see the login page ;) return true; } } else { if (log.isTraceEnabled()) { log.trace("Attempting to access a path which requires authentication. Forwarding to the " +"Authentication url [" + getLoginUrl() + "]"); } saveRequestAndRedirectToLogin(request, response); return false; } } 大致讲解一下,当我们登陆时提交的表单URL被FormAuthenticationFilter拦截后,会执行onAccessDenied方法,首先该方法会判断该请求是否是访问登陆URL的请求,如果否直接跳转到登陆页面,如果是再判断该请求是请求登陆的页面还是提交的是登陆的表单信息,如果是则返回登陆的页面,否则执行executeLogin方法,该方法具体怎么实现我们不用去管,有兴趣的同学可以看源码,我们直需要知道,登陆成功后会执行onLoginSuccess方法,登陆失败后会执行onLoginFailure。onLoginFailure默认处理是返回登陆页面,onLoginSuccess默认实现是返回登陆成功的页面,也就是跳转到登陆页面之前被拦截的那个页面(有点绕,慢慢品味)。 解决方法 好了,了解了Shiro过滤器原理之后,所有问题都迎刃而解了,前后端分离架构中,无非是把原先Shiro返回的视图改为返回Json。我们写一个AjaxFormAuthenticadtionFilter类继承FormAuthenticationFilter类,修改onAccessDenied、onLoginSuccess、onloginFailure方法,源码如下(这里就不返回json了,直接返回一个字符串代替): public class AjaxFormAuthenticationFilter extends FormAuthenticationFilter { private static final Logger log = LoggerFactory.getLogger(AjaxFormAuthenticationFilter.class); @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { if (isLoginRequest(request, response)) { if (isLoginSubmission(request, response)) { if (log.isTraceEnabled()) { log.trace("Login submission detected. Attempting to execute login."); } return executeLogin(request, response); } else { if (log.isTraceEnabled()) { log.trace("Login page view."); } //allow them to see the login page ;) return true; } } else { if (log.isTraceEnabled()) { log.trace("Attempting to access a path which requires authentication. Forwarding to the " + "Authentication url [" + getLoginUrl() + "]"); } response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.println("尚未登陆,拒绝访问"); out.flush(); out.close(); return false; } } @Override protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) { response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e) { e.printStackTrace(); } out.println("登陆成功"); out.flush(); out.close(); return true; } @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e1) { e1.printStackTrace(); } out.println("登陆失败"); out.flush(); out.close(); return false; } } 在这里前后端分离架构中springboot整合shiro算是完成了。
Linux用习惯了,突然切换到Windows环境,突然发现连个MySQL都不会装了,折腾了好久,记录一下安装过程。 一、下载安装包 到官网下载安装包,本文以8.0.15这个版本为准 下载好后解压到安装目录,以下是我在本机的安装目录 二、配置 在安装目录下新建一个名为data文件夹,并新建一个my.ini的配置文件,用文本编辑器打开my.ini,填写以下配置到里面 [mysqld] # 设置3306端口 port=3306 # 设置mysql的安装目录 basedir=D:\mysql # 设置mysql数据库的数据的存放目录 datadir=D:\mysql\data # 允许最大连接数 max_connections=200 # 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统 max_connect_errors=10 # 服务端使用的字符集默认为UTF8 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 default_authentication_plugin=mysql_native_password [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [client] # 设置mysql客户端连接服务端时默认使用的端口 port=3306 default-character-set=utf8 三、配置环境变量并安装服务 配置环境变量这一步就省略了,无非就是将bin目录添加到系统的path里,不会的看其他教程。设置好环境变量后,在cmd里输入以下内容安装mysql服务 mysqld --install 四、初始化并设置密码 在cmd里输入以下内容初始化数据库 mysqld --initialize --console 不出意外的话,上一步会输出一个初始化的密码,请记下这个密码,然后启动服务 net start mysql 登陆mysql,输入以下命令后,输入刚刚的初始密码 mysql -u root -p 接下来设置新密码 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; 五、结束
启动 1.直接启动 rabbitmq-server 2.作为后台服务启动 rabbitmq-server -detached 3.启动某个应用(在节点没有关闭的情况下) rabbitmqctl start_app 关闭 1.关闭节点和应用 rabbitmqctl stop 2.仅关闭应用不关闭节点 rabbitmqctl stop_app
一. Docker 介绍 docker是个开源的容器, 我们可以利用它来很方便地部署应用, 特别是搭建微服务的时候, 我们都经常用到, 本篇只讲如何在linux下如何安装docker, 并不会对docker的使用做过多介绍, 有兴趣的朋友可以查看其他资料. 二. 前提 本篇文章环境是基于kali linux发行版,由于kali是基于Debian发行版的, 所以对于Debian及衍生系列发行版(apt包管理工具)也同样适用. 三. 安装 kali安装docker只需要以下两个基础的包docker和docker-compose即可, 其他依赖包会自动安装. apt-get udpate #更新本地缓存 apt-get install docker docker-compose #安装docker 不出意外,安装完成后可以启动docker服务 service docker start 拉台镜像下来,测试一下吧! docker pull ubuntu:latest docker run ubuntu:latest /bin/echo "hello world"
一、区别 1.<context:annotation-config/>:用于激活已经在容器中注册过的bean上面的注解,例如@Autowired,@Resource。 2.<context:component-scan/>:具备<context:annotation-config/>功能,同时还能够在指定包下扫描注册bean。 二、举个例子 假如有A,B两个bean public class A{ @Autowired private B b; public B getB(){ return b; } public void setB(B b){ this.b = b; } } public class B{ } 通过xml在容器中注册 <bean id="b" class="xyz.stackoverflow.example.B"/> <bean id="a" class="xyz.stackoverflow.example.A"/> 这个时候输出a中的b是null,原因是因为类A中的@Autowired并没有起作用,我们在xml中加入<context:annotation-config/>就行了。 <context:annotation-config/> <bean id="b" class="xyz.stackoverflow.example.B"/> <bean id="a" class="xyz.stackoverflow.example.A"/> 或者在类A和类B上分别加上@Component注解,xml中直接用<context:component-scan/>也行。