shiro整合springboot前后端分离

 更新时间:2019年12月16日 09:57:38   作者:有梦想的咸鱼xx  
这篇文章主要介绍了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请求,同时封装一个统一的未登录或者未授权状态码的判断

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

相关文章

  • JAVA偏向锁的原理与实战

    JAVA偏向锁的原理与实战

    这篇文章主要为大家详细介绍了JAVA偏向锁的原理与实战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Java函数式编程(十):收集器

    Java函数式编程(十):收集器

    这篇文章主要介绍了Java函数式编程(十):收集器,本文是系列文章的第10篇,其它文章请参阅本文底部的相关文章,需要的朋友可以参考下
    2014-09-09
  • Java中的二维数组的赋值与输出方式

    Java中的二维数组的赋值与输出方式

    这篇文章主要介绍了Java中的二维数组的赋值与输出方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Java二维数组简单定义与使用方法示例

    Java二维数组简单定义与使用方法示例

    这篇文章主要介绍了Java二维数组简单定义与使用方法,结合实例形式简单分析了java二维数组的定义、使用方法及相关注意事项,需要的朋友可以参考下
    2017-10-10
  • java中的interface接口实例详解

    java中的interface接口实例详解

    这篇文章主要介绍了 java中的interface接口实例详解的相关资料,需要的朋友可以参考下
    2017-03-03
  • Java通过反射机制将对象封装成JSON和JsonArray格式

    Java通过反射机制将对象封装成JSON和JsonArray格式

    这篇文章主要介绍了Java通过反射机制将对象封装成JSON和JsonArray格式,JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法,需要的朋友可以参考下
    2023-10-10
  • Spring Boot2.6.0新特性之默认禁止循环引用

    Spring Boot2.6.0新特性之默认禁止循环引用

    Spring Boot2.6.0为我们带来很多好用的新特性/改进,这篇文章主要给大家介绍了关于Spring Boot2.6.0新特性之默认禁止循环引用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • Spring controller校验入参的方法详解

    Spring controller校验入参的方法详解

    项目中使用Springboot,在Controller中配置了@NotNull和@Valid,@Notnull不生效,@Valid生效,返回http status为400,本文给大家介绍了Spring controller校验入参的方法,需要的朋友可以参考下
    2024-06-06
  • Java两个List<T> 求交集,差集,并集,去重后的并集

    Java两个List<T> 求交集,差集,并集,去重后的并集

    本文主要介绍了Java两个List<T> 求交集,差集,并集,去重后的并集,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Spring MVC集成springfox-swagger2构建restful API的方法详解

    Spring MVC集成springfox-swagger2构建restful API的方法详解

    这篇文章主要给大家介绍了关于Spring MVC集成springfox-swagger2构建restful API的相关资料,文中介绍介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-06-06

最新评论