shiro整合springboot前后端分离

本文实例为大家分享了shiro整合springboot前后端分离的具体代码,供大家参考,具体内容如下

1、shiro整合springboot的配置

package com.hisi.config;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import com.hisi.shiro.LoginAuthorizationFilter;
import com.hisi.shiro.RestFilter;
import com.hisi.shiro.UserRealm;

/**
 * shiro权限管理的配置
 * @author xuguoqin
 * @date 2018年5月4日
 * @version 1.0
 */
@Configuration
public class ShiroConfig {

 /**
 * 安全管理器
 * @param realm
 * @return
 */
 @Bean
 public DefaultWebSecurityManager securityManager(){
 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
 securityManager.setRealm(userRealm());
 securityManager.setSessionManager(sessionManager());
 return securityManager;
 }

 /**
 * Realm配置
 * @return
 */
 @Bean
 public UserRealm userRealm(){
 return new UserRealm();
 }

 /**
 * SessionDAO配置
 * @return
 */
 @Bean
 public SessionDAO sessionDAO(){
 return new MemorySessionDAO();
 }

 /**
 * sessionManager配置
 * @param sessionDAO
 * @return
 */
 @Bean
 public DefaultWebSessionManager sessionManager(){
 DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
 sessionManager.setSessionDAO(sessionDAO());
 return sessionManager;
 }

 /**
 * shiroFilter配置
 * @param securityManager
 * @return
 */
 @Bean
 public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){

 ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
 shiroFilter.setSecurityManager(securityManager());
 Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
 filters.put("token", new LoginAuthorizationFilter());
 filters.put("corsFilter", new RestFilter());
 shiroFilter.setFilters(filters);
 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
 filterChainDefinitionMap.put("/user/login", "corsFilter,anon");
 filterChainDefinitionMap.put("/user/logout", "corsFilter,anon");
 filterChainDefinitionMap.put("/user/**", "corsFilter,token");
 shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
 return shiroFilter;
 }

 /**
   * 保证实现了Shiro内部lifecycle函数的bean执行
   */
  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  /**
   * 启用shrio授权注解拦截方式,AOP式方法级权限检查
   */
  @Bean
  @DependsOn(value = "lifecycleBeanPostProcessor") //依赖其他bean的初始化
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    return new DefaultAdvisorAutoProxyCreator();
  }

 /**
 * 加入注解的使用,不加入这个注解不生效 使用shiro框架提供的切面类,用于创建代理对象
 * @param securityManager
 * @return
 */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }

}

2、这里配置的两个过滤器RestFilter和LoginAuthorizationFilter,RestFilter是用于解决前后端分离时的跨域问题,服务端在响应头设置可以接受的请求参数

package com.hisi.shiro;

import java.io.IOException;
import java.util.Optional;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 前后端分离RESTful接口过滤器
 *
 * @author xuguoqin
 *
 */
public class RestFilter implements Filter {

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {

 }

 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  throws IOException, ServletException {
 HttpServletRequest req = null;
 if (request instanceof HttpServletRequest) {
  req = (HttpServletRequest) request;
 }
 HttpServletResponse res = null;
 if (response instanceof HttpServletResponse) {
  res = (HttpServletResponse) response;
 }
 if (req != null && res != null) {
  //设置允许传递的参数
  res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  //设置允许带上cookie
  res.setHeader("Access-Control-Allow-Credentials", "true");
  String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer"));
  //设置允许的请求来源
  res.setHeader("Access-Control-Allow-Origin", origin);
  //设置允许的请求方法
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
 }
 chain.doFilter(request, response);
 }

 @Override
 public void destroy() {

 }

}

前者ajax请求的时候应该带上参数

$.ajax({
type: "GET",
url: url,
xhrFields: {
  withCredentials: true // 携带跨域cookie
},
processData: false,
success: function(data) {
  console.log(data);
}
});

3、LoginAuthorizationFilter主要是对未登录的用户进行过滤然后返回json数据给前端,之前遇到的问题就是shiro配置的loginUrl会导致出现302的问题,在前后端分离的项目中,页面的跳转应该由前端来进行控制,这里前端使用的是vue框架,我需要对shiro中未登录的过滤器FormAuthenticationFilter进行重构

package com.hisi.shiro;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSONObject;
import com.commons.model.YfpjResult;
import com.hisi.mapper.HisiUserMapper;
import com.hisi.model.HisiUser;
import com.hisi.util.Constant;
import com.hisi.util.UserAuthStatusEnum;

/**
 * shiro未登录反回状态码
 * @author xuguoqin
 * @date 2018年5月10日
 * @version 1.0
 */
public class LoginAuthorizationFilter extends FormAuthenticationFilter {

 /**
 * 这个方法是未登录需要执行的方法
 */
 @Override
 protected boolean onAccessDenied(ServletRequest request,
      ServletResponse response) throws IOException {

 HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response; 

    Subject subject = getSubject(request, response);
    if (subject.getPrincipal() == null) {
     //设置响应头
 httpResponse.setCharacterEncoding("UTF-8");
 httpResponse.setContentType("application/json");
 //设置返回的数据
 YfpjResult result = YfpjResult.build(UserAuthStatusEnum.UNLOGIN.getCode(), UserAuthStatusEnum.UNLOGIN.getMsg());
 //写回给客户端
 PrintWriter out = httpResponse.getWriter();
 out.write(JSONObject.toJSONString(result));
 //刷新和关闭输出流
 out.flush();
 out.close();
    } else {
     //设置响应头
   httpResponse.setCharacterEncoding("UTF-8");
   httpResponse.setContentType("application/json");
   //设置返回的数据
   YfpjResult result = YfpjResult.build(UserAuthStatusEnum.UNAUTH.getCode(), UserAuthStatusEnum.UNAUTH.getMsg());
   //写回给客户端
   PrintWriter out = httpResponse.getWriter();
   out.write(JSONObject.toJSONString(result));
   //刷新和关闭输出流
   out.flush();
   out.close();
    }
    return false;
 }
}

4.以后在进行前后端分离的项目开发的时候,可以前端封装一个允许带cookie的ajax请求,同时封装一个统一的未登录或者未授权状态码的判断

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring boot整合shiro+jwt实现前后端分离

    本文实例为大家分享了Spring boot整合shiro+jwt实现前后端分离的具体代码,供大家参考,具体内容如下 这里内容很少很多都为贴的代码,具体内容我经过了看源码和帖子加了注释.帖子就没用太多的内容 先下载shiro和jwt的jar包 <!-- shiro包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId

  • SpringBoot + Shiro前后端分离权限

    shiro 验证通过后的信息保存在session 中,而ajax 每次传的都是不同的sessionid ,所以主要的区别就是需要修改shiro获取sessionid的方式.这里使用的是登录后将后台的sessionid 传到前端然后存放到 cookie(这个存放的地方视情况而定),然后每次请求后端时在Header中携带此信息,这里起名为Authorization shiro 中 默认获取Sessionid的类是 DefaultWebSessionManager 所以需要重写此类 import or

  • Shiro+Cas微服务化及前后端完全分离

    本文实例为大家分享了Shiro Cas微服务化及前后端完全分离,供大家参考,具体内容如下 shiro+cas微服务化笔记 1.Spring Boot 配置 有如下两个配置文件:ShiroBaseConfig.java import lombok.extern.log4j.Log4j; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.cache.MemoryConstrainedCacheManager; im

  • shiro整合springboot前后端分离

    本文实例为大家分享了shiro整合springboot前后端分离的具体代码,供大家参考,具体内容如下 1.shiro整合springboot的配置 package com.hisi.config; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.session.mgt.eis.MemorySessionDAO; import org

  • springBoot前后端分离项目中shiro的302跳转问题

    springBoot前后端分离项目shiro的302跳转 项目是使用的springboot ,使用的shiro做的用户鉴权.在前端请求时当用户信息失效,session失效的时候,shiro会重定向到配置的login.jsp 页面,或者是自己配置的logUrl. 因是前后端分离项目,与静态资源文件分离,固重定向后,接着会404. 经过查找网上配置资料,发现302原因是 FormAuthenticationFilter中onAccessDenied 方法做了相应处理.那知道问题所在,就可以有解决方了

  • vue+springboot前后端分离实现单点登录跨域问题解决方法

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘. 刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)...,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑. 我面临的第一个问题是跨域,浏览器控制台直接报CORS,

  • 部署vue+Springboot前后端分离项目的步骤实现

    单页应用 vue经常被用来开发单页应用(SinglePage Web Application,SPA),什么叫做单页应用呢,也就是只有一张web页面的应用,单页应用的跳转只需要刷新局部资源,大大加快的了我们页面的响应速度 前端页面打包 打开vue工程,在项目根目录下创建一个配置文件:vue.config.js,然后在里面写入以下内容: module.exports = { assetsDir: 'static', // 静态资源保存路径 outputDir: 'dist', // 打包后生成的文

  • Vue+SpringBoot前后端分离中的跨域问题

    在前后端分离开发中,需要前端调用后端api并进行内容显示,如果前后端开发都在一台主机上,则会由于浏览器的同源策略限制,出现跨域问题(协议.域名.端口号不同等),导致不能正常调用api接口,给开发带来不便. 封装api请求 import axios from 'axios' //axios.create创建一个axios实例,并对该实例编写配置,后续所有通过实例发送的请求都受当前配置约束 const $http = axios.create({ baseURL: '', timeout: 1000

  • IDEA教程创建SpringBoot前后端分离项目示例图解

    目录 创建springboot项目 测试项目 按照MVC格式创建数据库项目 总结 springboot就是简化Spring应用中的初始化配置,快速创建项目而生的. 创建springboot项目 代开idea,点击File->New->Project,弹出如下对话框 输入组织.工程名,选择maven工程,注意:java版本号选择8 可以根据自己项目的需求选择依赖包,系统会自动将这些依赖包写入maven的pom文件,如下选择Spring Web.myBtias.mySQL驱动等.无需担心漏掉依赖包

  • SpringBoot前后端分离实现验证码操作

    目录 1.SpringBoot版本 2.引入依赖 3.实现思路 新建验证码枚举类 定义验证码配置信息 定义验证逻辑生成类 在控制层上定义验证码生成接口 效果体验 在前端调用接口 1.SpringBoot版本 本文基于的Spring Boot的版本是2.6.7 . 2.引入依赖 captcha一款超简单的验证码生成,还挺好玩的.还有中文验证码,动态验证码. .在项目中pom.xml配置文件中添加依赖,如下: <!--验证码--> <dependency> <groupId>

  • SpringBoot前后端分离解决跨域问题的3种解决方案总结

    目录 什么是跨域 跨域问题的解决策略 三种解决方法 总结 什么是跨域 想要知道什么是跨域的话,我们可以通过一个小案例简单了解一下跨域的概念:在项目代码编写的时候,我们将前端项目代码和后端的项目代码相分离开,一个运行在本地的8080端口一个运行在本地的8888端口,这也就是我们常说的前后端分离项目.现在使用前端的请求去调用后端的接口,就会产生以下的错误 Access to XMLHttpRequest at 'http://localhost:8888/请求名' from origin ‘http

  • SpringBoot前后端分离实现个人博客系统

    目录 一.项目简介 二.环境介绍 三.系统展示 四.核心代码展示 五.项目总结 一.项目简介 本项目使用springboot+mybatis+前端vue,使用前后端分离架构实现的个人博客系统,共7个模块,首页,写博客,博客详情页,评论管理,文章分类,标签管理和文章归档.该项目没有后端管理功能,比较适合用于大作业! 二.环境介绍 语言环境:Java:  jdk1.8 数据库:Mysql: mysql5.7/redis 应用服务器:Tomcat:  tomcat8.5.31 开发工具:IDEA或ec

随机推荐