shiro整合springboot前后端分离
作者:有梦想的咸鱼xx 发布时间:2022-02-22 10:40:31
标签: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请求,同时封装一个统一的未登录或者未授权状态码的判断
来源:https://blog.csdn.net/qq_31489805/article/details/80267916


猜你喜欢
- 前言一般数据库的表结构都会有update_time,修改时间,因为这个字段基本与业务没有太大关联,因此开发过程中经常会忘记设置这两个字段的值
- 一、实验目的1. 掌握各种高级UI控件的基本使用;2. 能够实现Tab切换效果。二、实验任务1. 根据原型图设计界面;2. 实现Tab切换;
- 本文实例为大家分享了java音乐播放器的具体代码,供大家参考,具体内容如下源码:package baidu;import java.awt.
- XML的特点是功能全面,但标签繁琐,格式复杂。在Web上使用XML现在越来越少,取而代之的是JSON这种数据结构。JSON是JavaScri
- @EqualsAndHashCode注解@EqualsAndHashCode注解的作用就是自动实现model类的equals方法和hashc
- C#的System.Collections命名空间包含可使用的集合类和相关的接口,提供了集合的基本功能。包括了.NET下的非泛型集合类以及非
- 在Activity之间传递数据还可以利用一些技巧,不管windows还是Linux操作系统,都会支持一种叫剪切板的技术,也就是某一个程序将一
- 原始数据:string input = "3,7,2,8,1,9,1,34,67,78,22";要处理为:string[
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:package com.example.yanlei.yl4;import androi
- 本文实例为大家分享了WPF ProgressBar实现实时进度的具体代码,供大家参考,具体内容如下简单测试,页面如图:利用上班的一点点空闲时
- 矢量室内地图开发因为公司项目的需要,需要开发一套室内地图,并实现路线的规划功能。因为之前没做过这方面的开发,相关的资料也比较少,所以只能一个
- 目录概述1 技术工具2 构建Spring Boot工程3 开始编写测试和代码1 Controller2 Service3 Repositor
- 我就废话不多说了,大家还是直接看代码吧~package cn.nxl2018;class Test{ //十进制常量赋值 &n
- 前言开发中,免不了会用到多边形、多角星等图案,比较常用的多边形比如雷达图、多角星比如评价星级的五角星等,本篇文章就使用Flutter绘制封装
- ContentProvider是内容提供者,可以跨进程提供数据。大家都知道,ContentProvider的启动,是在Application
- 实例如下:public String stripHtml(String content) { // <p>段落替换为换行 con
- 1、数组数组其实也是一种数据格式,不过是一种复合类型,它可以存储多个同类型的值。使用数组可以将同类型的变量整合起来管理,比如说我们现在要记录
- 部分同学在使用 idea 时可能会遇到输入 sout 无法出现自动补全 System.out.println();的情况,其实 idea 默
- 经过测试 将resultMap="java.lang.Integer"改成resultType="java.l
- 网络中数据传输经常是xml或者json,现在做的一个项目之前调其他系统接口都是返回的xml格式,刚刚遇到一个返回json格式数据的接口,通过