简述:
shiro是根据sessionID来识别是不是同一个request,但如果前后分离的话,就会出现跨域的问题,session很可能就会发生变化,这样就需要用一个标记来表明是同一个请求
1.shiro有三大组件
1.1 Subject
代表当前与程序进行交互的使用者
1.2 SecurityManager
是 Shiro 架构的心脏,并作为一种“保护伞”对象来协调内部的安全组件共同构成一个对象图
1.3 Realms
一个用于认证和授权的类
2.首先前后端分离会有跨域问题,还有复杂请求问题
2.1跨域如下
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 目的: 跨域访问控制
* 做前后分离的话,这个也是必配的
* 备注说明:
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 允许任何域名使用
corsConfiguration.addAllowedOrigin("*");
// 允许任何头
corsConfiguration.addAllowedHeader("*");
// 允许任何方法(post、get等)
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 对接口配置跨域设置
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
2.2复杂请求如下
package com.example.demo;
import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 目的: 过滤OPTIONS请求
* 继承shiro 的form表单过滤器,对 OPTIONS 请求进行过滤。
* 前后端分离项目中,由于跨域,会导致复杂请求,即会发送preflighted request,这样会导致在GET/POST等请求之前会先发一个OPTIONS请求,但OPTIONS请求并不带shiro
* 的'authToken'字段(shiro的SessionId),即OPTIONS请求不能通过shiro验证,会返回未认证的信息。
*
* 备注说明: 需要在 shiroConfig 进行注册
*/
public class CORSAuthenticationFilter extends FormAuthenticationFilter {
/**
* 直接过滤可以访问的请求类型
*/
private static final String REQUET_TYPE = "OPTIONS";
public CORSAuthenticationFilter() {
super();
}
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals(REQUET_TYPE)) {
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
@Override
protected boolean onAccessDenied