首页> 文章> 详情

spring boot整合spring security4自定义配置

教程分享 > Java教程 (5784) 2024-04-17 12:31:24
spring boot整合spring security4自定义配置
1.项目结构图
项目结构图
2.自定义spring拦截器UrlInterceptor
package com.leftso.config;

import org.springframework.web.servlet.HandlerInterceptor;

/**
 * url 拦截器,实现该接口并在实现类上添加注解@Component,将会自动注入spring拦截器
 * 
 * @author leftso
 *
 */

public interface UrlInterceptor extends HandlerInterceptor {
	/***
	 * 需要拦截的url
	 * 
	 * @return
	 */
	String[] pathPatterns();

	/***
	 * 排除拦截
	 * 
	 * @return
	 */
	String[] excludePathPatterns();

	int order();
}
3.获取spring context容器(为了后面动态添加拦截器)
package com.leftso.config;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 
 * <pre>
 * [Summary]
 * 获取spring容器
 * [Detail]
 * TODO
 * [Author]
 * leftso
 * [Version]
 * v1.0
 * 2017年3月23日下午8:59:15
 * </pre>
 */
@Component
public class SpringUtils implements ApplicationContextAware {
	public static ApplicationContext applicationContext = null;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		if (SpringUtils.applicationContext == null) {
			SpringUtils.applicationContext = applicationContext;
		}

	}

}
4.继承WebMvcConfigurerAdapter重写配置,动态添加拦截器
package com.leftso.config;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * 添加自定义的拦截器
 * 
 * @author
 *
 */
@Configuration
public class MvcConfigurerAdapter extends WebMvcConfigurerAdapter {

	@Autowired
	SpringUtils springUtils;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		super.addInterceptors(registry);
		@SuppressWarnings("static-access")
		Map<String, UrlInterceptor> urlInterceptors = springUtils.applicationContext
				.getBeansOfType(UrlInterceptor.class);
		if (!StringUtils.isEmpty(urlInterceptors)) {
			Set<String> keys = urlInterceptors.keySet();
			Iterator<String> it = keys.iterator();
			while (it.hasNext()) {
				String key = it.next();
				UrlInterceptor urlInterceptor = urlInterceptors.get(key);
				String[] pathPatterns = urlInterceptor.pathPatterns();
				if (pathPatterns == null) {
					pathPatterns = new String[] {};
				}
				String[] excludePathPatterns = urlInterceptor.excludePathPatterns();
				if (excludePathPatterns == null) {
					excludePathPatterns = new String[] {};
				}
				registry.addInterceptor(urlInterceptor).addPathPatterns(pathPatterns)
						.excludePathPatterns(excludePathPatterns);
			}
		}
	}

}
5.从这里开始,进行spring security相关配置,配置启用spring security
package com.leftso.security.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().anyRequest().permitAll();
	}

	/**
	 * 需要拦截的url
	 * 
	 * @return
	 */
	public String[] securityMethodUrlPatterns() {

		return new String[] { "/security/**" };
	}
}
注意:这里的http.authorizeRequests().anyRequest().permitAll();允许所有访问是为了后面自定义拦截器,不使用默认的spring filter
6.自定义一个spring security认证服务
package com.leftso.security.service;

import javax.servlet.http.HttpServletRequest;

/**
 * spring security 业务处理
 * 
 * @author LEFTSO
 *
 */
public interface SecurityService {
	/**
	 * 获取认证信息
	 * 
	 * @param httpServletRequest
	 */
	public void authenticate(HttpServletRequest httpServletRequest);

	/**
	 * 释放认证信息
	 */
	public void release();
}

接口里面有两个方法,一个是通过请求信息生成认证信息,一个是释放认证信息资源
实现类:
package com.leftso.security.service;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.leftso.security.UserAuthentication;

@Component
public class SecurityServiceimp implements SecurityService {

	@Override
	public void authenticate(HttpServletRequest httpServletRequest) {
		// 通过http请求cookie或者其他方式拿到用户登录后的凭证
		String name = httpServletRequest.getParameter("name");
		if ("leftso".equals(name)) {
			// 创建一个认证信息实例
			// 1.创建当前用户的角色信息
			List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
			authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
			// 2.实例创建
			Authentication authentication = new UserAuthentication(authorities, name);
			authentication.setAuthenticated(true);
			// 添加到安全容器
			SecurityContextHolder.getContext().setAuthentication(authentication);
		}else{
			SecurityContextHolder.clearContext();
		}
	}

	@Override
	public void release() {
		SecurityContextHolder.clearContext();
	}

}
这里的认证只是简单的写死了传递一个name参数且值为leftso才会认证成功并且添加一个ROLE_ADMIN的角色,当然实际应用这里应该去数据库查询认证,做好缓存等操作
下面是一个上面用到的自定义认证实现:
package com.leftso.security;

import java.util.Collection;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

/**
 * 自定义用户认证
 * 
 * @author leftso
 *
 */
public class UserAuthentication extends AbstractAuthenticationToken {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;

	public UserAuthentication(Collection<? extends GrantedAuthority> authorities) {
		super(authorities);
	}

	public UserAuthentication(Collection<? extends GrantedAuthority> authorities, String name) {
		super(authorities);
		this.name = name;
	}

	@Override
	public Object getCredentials() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getPrincipal() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getName() {
		return name;
	}

}

7.最重要的入口来了,自定义一个拦截器作为需要安全认证的入口
package com.leftso.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;

import com.leftso.config.UrlInterceptor;
import com.leftso.security.config.WebSecurityConfig;
import com.leftso.security.service.SecurityService;

/**
 * spring security安全拦截器
 * 
 * @author leftso
 *
 */
@Component
public class SecurityInterceptor implements UrlInterceptor {

	@Autowired
	WebSecurityConfig abstractWebSecurityConfig;

	@Autowired
	SecurityService securityService;

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3)
			throws Exception {
		// 后置释放认证信息
		securityService.release();

	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3)
			throws Exception {

	}

	@Override
	public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse arg1, Object arg2)
			throws Exception {
		System.out.println("---Security:Interceptor--");
		// 前置处理认证信息
		securityService.authenticate(httpServletRequest);
		return true;
	}

	@Override
	public String[] pathPatterns() {
		// 配置中获取拦截信息
		return abstractWebSecurityConfig.securityMethodUrlPatterns();
	}

	@Override
	public int order() {

		return 0;
	}

	@Override
	public String[] excludePathPatterns() {
		// TODO Auto-generated method stub
		return null;
	}

}
拦截器前置调用获取用户信息生成认证信息
拦截器后置释放认证信息资源
注意前置必须返回TRUE,否则不能继续


8.定义了两个简单的controller用于测试
package com.leftso.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexCtrl {

	@GetMapping("")
	public String index() {
		return "Welcome Index Page.";
	}

	@GetMapping("p1")
	public String p1() {
		return "P1";
	}

	@GetMapping("login")
	public String login() {
		return "Login Page";
	}
}
package com.leftso.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SecurityCtrl {

	@PreAuthorize("hasRole('ROLE_ADMIN')")
	@GetMapping("/security/s1")
	public String s1() {
		return "s1";
	}

	@GetMapping("/security/s2")
	public String s2() {
		return "s2";
	}

}

启动项目:
首页
继续访问受保护的资源链接:
403
由于没有权限,报错403禁止访问,(说明/security/**下面所有资源都会被拦截)

但是访问s2:
222
不难发现可以访问s2,这是为啥呢?
区别
需要保护的资源必须加上需要访问的权限角色


好了言归正传,如何访问到s1的资源呢?如下:
成功访问
说明:实际应用中这个认证的信息是登录后的令牌并且是加密的,可能是放session中可能是cookie中

https://www.leftso.com/article/129.html

相关文章
spring security常用注解@Secured、@PreAuthorize 、@PostAuthorize说明,Java编程,spring security
spring boot 入门之security oauth2 jwt完美整合例子,Java编程中spring boot框架+spring security框架+spring security o...
Java编程中spring security4是一个spring框架项目的一个安全方面的项目。主要用于用户认证,授权,角色认证
spring boot 2.0 security 5.0 整合,实现自定义表单登录。spring boot 2.0框架使用。
Java编程中Spring Boot整合RabbitMQ实现消息中间件RabbitMQ的使用
Java编程中spring boot项目如何获取spring容器applicationContext
Spring Security 配置多个Authentication Providers认证器
Java编程之Spring Boot通过JMSTemplate 整合ActiveMQ
Java编程之Spring Boot中使用jsp视图模板
引言在这篇文章中,我们将讨论如何使用Spring Boot Security OAuth2保护REST API
解决spring security 整合到spring boot中,UserDetailsService接口的loadUserByUsername方法参数username输入为空问题。一  检查...
1.概述本文继续使用spring boot 和Spring Security系列进行注册,并着重于如何正确实现角色和权限
Java编程中spring boot项目动态添加拦截器Interceptor
本文主要翻译spring官方的基于spring security框架的oauth2开发指南,spring,oauth2,spring框架,Java编程