shiro整合springboot前后端分离

作者:有梦想的咸鱼xx 时间:2022-02-22 10:40:31 

本文实例为大家分享了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请求,同时封装一个统一的未登录或者未授权状态码的判断

来源:https://blog.csdn.net/qq_31489805/article/details/80267916

标签:shiro,springboot,前后端分离
0
投稿

猜你喜欢

  • IDEA自定义常用代码块及自定义快捷摸板

    2022-01-13 18:54:22
  • 简单谈谈java的异常处理(Try Catch Finally)

    2021-08-01 12:40:02
  • C#有效防止同一账号多次登录(附三种方法)

    2023-05-23 10:32:45
  • C# 实现绘制PDF嵌套表格案例详解

    2023-05-25 11:57:13
  • C#实现文件上传以及多文件上传功能

    2023-06-19 15:36:17
  • Iconfont(矢量图标)+iconmoon(图标svg互转)配合javascript实现社交分享系统

    2023-09-28 13:23:19
  • RSA密钥--JAVA和C#的区别及联系

    2022-09-18 12:16:44
  • java中thread线程start和run的区别

    2023-09-30 13:12:16
  • 详解如何在Java中实现堆排序算法

    2023-11-11 11:34:46
  • android中RecyclerView自定义分割线实现

    2023-08-03 17:37:47
  • SpringCloudAlibaba整合Feign实现远程HTTP调用的简单示例

    2023-11-19 16:16:05
  • Java List的remove()方法踩坑

    2021-05-27 05:17:58
  • 自己动手写的mybatis分页插件(极其简单好用)

    2023-11-01 18:12:09
  • Java中Equals使用方法汇总

    2022-09-14 23:08:28
  • WinForm实现窗体最大化并遮盖任务栏的方法

    2022-09-19 20:00:19
  • Java中String类常用类型实例总结

    2023-07-06 19:15:43
  • Java NIO:浅析IO模型_动力节点Java学院整理

    2022-01-17 17:07:38
  • 详解Android内存优化策略

    2022-01-03 13:52:10
  • C#开发Windows服务实例之实现禁止QQ运行

    2023-04-13 03:29:29
  • Java数据结构之双向链表的实现

    2023-09-17 16:21:45
  • asp之家 软件编程 m.aspxhome.com