springboot swagger2 与 shiro 集成采坑

1.集成了shiro之后,swagger2页面总是报错,报类型转换错误。swagger2 json转换错误。如果springboot采用gson做的json转换,必须自定义类转换。

	@Bean
	public GsonHttpMessageConverter gsonHttpMessageConverter() {
		GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
		converter.setGson(new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss")
				.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter()).create());
		return converter;
	}
   // 使用gson格式时候,会报错。
	class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {
		@Override
		public JsonElement serialize(Json src, Type typeOfSrc, JsonSerializationContext context) {
			final JsonParser parser = new JsonParser();
			return parser.parse(src.value());
		}
	}

2.shiro会话类无法转换,使用了devtools模式时,shiro 会话类加载不一致。导致类型转换错误。定义spring-devtools.properties配置文件。把会话类所在的jar包排除。或者把shiro的包用热加载。

3.swagger2 页面能正常访问,但是模拟接口报错。

思路一,swagger2 应该可以配置请求头的地方,吧shiro的会话信息带上,这样可以访问模拟接口。我没找到方法。

思路二,对于swagger2 请求的接口,放开请求,shiro放开拦截。测试环境开启,生产环境关闭

这是对页面请求的配置。保证测试环境能够访问页面,生产环境关闭页面。

public class TestAuthenticationFilter extends AuthenticationFilter {

//	private static final Logger log = LoggerFactory.getLogger(TestAuthenticationFilter.class);

	protected static boolean testEnvironment=false;

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		if (isTestEnvironment()) {
			return true;
		}
		response.setContentType("application/json");
		response.setCharacterEncoding("utf-8");
		response.getWriter().write(JSON.toJSONString(ResultBuilder.genExpResult(new BizException(BaseExcCodesEnum.NO_RIGHT))));
		return false;

	}

	public static boolean isTestEnvironment() {
		return testEnvironment;
	}

	public static void setTestEnvironment(boolean testEnvironment) {
		TestAuthenticationFilter.testEnvironment = testEnvironment;
	}

}

	@Bean
	protected ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		shiroFilter.setLoginUrl("/manager/login");
		shiroFilter.setSecurityManager(securityManager);

		Map<String, Filter> filters = new HashMap<>();
		TestAuthenticationFilter testAuthenticationFilter=new TestAuthenticationFilter();
		TestAuthenticationFilter.setTestEnvironment(env.getProperty("app.testEnvironment",Boolean.class));
		
		ApiAuthenticationFilter apiAuthenticationFilter=new ApiAuthenticationFilter();

		filters.put("test",testAuthenticationFilter);
		filters.put("api",apiAuthenticationFilter);
		
		shiroFilter.setFilters(filters);

		Map<String, String> filterMap = new LinkedHashMap<>();
		filterMap.put("/statics/**", "anon");
		filterMap.put("/js/**", "anon");
		filterMap.put("/favicon.ico", "anon");
		filterMap.put("/sys/manager/login", "anon");
		filterMap.put("/sys/manager/forgetPassword", "anon");
		filterMap.put("/sys/manager/captcha", "anon");
        filterMap.put("/sys/manager/logout", "anon");
		
	

		filterMap.put("/swagger-ui.html", "test");
		filterMap.put("/swagger-resources/**", "test");
		filterMap.put("/image/**","test");
		filterMap.put("/v2/api-docs", "test");
		filterMap.put("/webjars/**", "test");

		filterMap.put("/**", "api");
		
		shiroFilter.setFilterChainDefinitionMap(filterMap);
		return shiroFilter;
	}

对权限的判断,测试环境开启无需验证shiro权限。

    @Bean
    public TestAopAllianceAnnotationsAuthorizingMethodInterceptor apiAopAllianceAnnotationsAuthorizingMethodInterceptor() {
        TestAopAllianceAnnotationsAuthorizingMethodInterceptor aopAllianceAnnotationsAuthorizingMethodInterceptor = new TestAopAllianceAnnotationsAuthorizingMethodInterceptor();
        aopAllianceAnnotationsAuthorizingMethodInterceptor.setTestEnvironment(env.getProperty("app.testEnvironment",Boolean.class));
        return aopAllianceAnnotationsAuthorizingMethodInterceptor;
    }
    
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        advisor.setAdvice(apiAopAllianceAnnotationsAuthorizingMethodInterceptor());
        return advisor;
    }

public class TestAopAllianceAnnotationsAuthorizingMethodInterceptor extends AopAllianceAnnotationsAuthorizingMethodInterceptor {

	private boolean testEnvironment = false;

	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
		if (testEnvironment) {
			return mi.proceed();
		} else {
			return super.invoke(mi);
		}

	}

	public boolean isTestEnvironment() {
		return testEnvironment;
	}

	public void setTestEnvironment(boolean testEnvironment) {
		this.testEnvironment = testEnvironment;
	}

}

4. shiro 事务不生效问题

如果定义的Realm引用了service,延迟Realm实现中Service对象的初始化时间,这样就可以保证Service实际初始化的时候会被BeanPostProcessor拦截,

public class UserNamePassWordRealm extends AbstractUserRealm {
  

    private static final Logger logger = LoggerFactory.getLogger(UserNamePassWordRealm.class);
    
    @Autowired
    @Lazy
    //创建具有事务功能的代理对象
    private UserService userService;

5.跨域问题,跨域访问会发送option请求,请求会被shiro拦截报跨域问题,

	@Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		HttpServletRequest httpRequest = WebUtils.toHttp(request);
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
        	String originHeader = httpRequest.getHeader("Origin");
        	if(allowOrigins.contains(originHeader)){
        		  httpResponse.setHeader("Access-control-Allow-Origin",originHeader);
                  httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                  httpResponse.setHeader("Access-Control-Allow-Headers","Origin,Accept,x-requested-with,content-type,X-AUTH-SESSION");
                  httpResponse.setHeader("Access-Control-Expose-Headers", "X-AUTH-SESSION");
                  httpResponse.setHeader("Access-Control-Max-Age", "3600");
                  httpResponse.setStatus(HttpStatus.OK.value());
                  return true;
        	}          
        }
        Subject subject = getSubject(request, response);
        return subject.isAuthenticated();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值