您的位置:首页 > 编程语言 > Java开发

spring boot 中spring security使用数据库保存权限

2017-12-24 10:44 1101 查看

WebSecurityConfig

package com.maven;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.maven.security.MyFilterSecurityInterceptor;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
private DataSource dataSource;

@Autowired
@Qualifier("myUserDetailsService")
private UserDetailsService userDetailsService;

@Autowired
@Qualifier("myAccessDecisionManager")
private AccessDecisionManager accessDecisionManager;

@Autowired
@Qualifier("mySecurityMetadataSource")
private FilterInvocationSecurityMetadataSource securityMetadataSource;

@Autowired
private AuthenticationManagerBuilder authenticationManagerBuilder;

private AuthenticationManager authenticationManager;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
//自定义过滤器,把资源配置存放到数据库中
.addFilterBefore(filter(),FilterSecurityInterceptor.class)
.exceptionHandling()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.invalidateHttpSession(true)
.deleteCookies("remember-me")
.and()
.rememberMe()
.tokenRepository(tokenRepository())
.tokenValiditySeconds(1209600)//默认2周
.rememberMeCookieName("remember-me")
.userDetailsService(userDetailsService)
.rememberMeParameter("remember-me");
}

private PersistentTokenRepository tokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}

// 配置AuthenticationManager
@Bean
public AuthenticationManager authenticationManagerBean() {
authenticationManagerBuilder.authenticationProvider(authenticationProvider());
return authenticationManagerBuilder.getOrBuild();
}

// 获取AuthenticationManager,避免多次调用authenticationManagerBean()
public AuthenticationManager getAuthenticationManager() {
if (this.authenticationManager == null) {
return authenticationManagerBean();
} else {
return this.authenticationManager;
}
}

// 自定义JpaFilterSecurityInterceptor过滤器
public MyFilterSecurityInterceptor filter() throws Exception {
MyFilterSecurityInterceptor filter = new MyFilterSecurityInterceptor();
// 认证管理器,实现用户认证的入口
filter.setAuthenticationManager(getAuthenticationManager());
// 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源
filter.setAccessDecisionManager(accessDecisionManager);
// 资源源数据定义,即定义某一资源可以被哪些角色访问
filter.setSecurityMetadataSource(securityMetadataSource);
return filter;
}

// 配置DaoAuthenticationProvider
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
// 设置不隐藏UserNotFoundExceptions
authenticationProvider.setHideUserNotFoundExceptions(false);
// 设置自定义UserDetailsService
authenticationProvider.setUserDetailsService(userDetailsService);
// 设置密码加密方式
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
authenticationProvider.setPasswordEncoder(passwordEncoder);
return authenticationProvider;
}

}


MyAccessDecisionManager

/**
* copyright by liukai
*/
package com.maven.security;

import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

@Service("myAccessDecisionManager")
public class MyAccessDecisionManager implements AccessDecisionManager{

private final static Logger logger = LoggerFactory.getLogger(MyAccessDecisionManager.class);

/* (non-Javadoc)
* @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
*/
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) {
return; //如果访问资源不需要任何权限则直接通过
}
//所请求的资源拥有的权限(一个资源对多个权限)
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig) ca).getAttribute();
// ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
for (GrantedAuthority ga : authentication.getAuthorities()) {
logger.info("该资源所需要的权限是:"+needRole +",当前用户的权限是:"+ ga.getAuthority());
if (needRole.trim().equals(ga.getAuthority().trim())) {
return;
}
}
}
logger.info("权限不足,无法访问!");
throw new AccessDeniedException("不允许访问!");
}

/* (non-Javadoc)
* @see org.springframework.security.access.AccessDecisionManager#supports(org.springframework.security.access.ConfigAttribute)
*/
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}

/* (non-Javadoc)
* @see org.springframework.security.access.AccessDecisionManager#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return true;
}

}


MyFilterSecurityInterceptor

/**
* copyright by liukai
*/
package com.maven.security;

import java.io.IOException;

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 org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{

private FilterInvocationSecurityMetadataSource securityMetadataSource;

/**
* @return the securityMetadataSource
*/
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
}

/**
* @param securityMetadataSource the securityMetadataSource to set
*/
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}

/* (non-Javadoc)
* @see org.springframework.security.access.intercept.AbstractSecurityInterceptor#getSecureObjectClass()
*/
@Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}

/* (non-Javadoc)
* @see org.springframework.security.access.intercept.AbstractSecurityInterceptor#obtainSecurityMetadataSource()
*/
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return securityMetadataSource;
}

/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}

public void invoke(FilterInvocation fi) throws IOException, ServletException {
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}

/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
@Override
public void destroy() {

}

}


MySecurityMetadataSource

/**
* copyright by liukai
*/
package com.maven.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import com.maven.auth.service.AuthService;

@Service("mySecurityMetadataSource")
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource{

private final static Logger logger = LoggerFactory.getLogger(MySecurityMetadataSource.class);

private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

public MySecurityMetadataSource(AuthService authService) {
//查询所有资源路径和角色
List<Map<String,Object>> resourceRoles = authService.findAllResourceAndRole();
//根据URL组装权限Map key为URL,集合为权限集合
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
for(Map<String,Object> resourceRole :resourceRoles) {
ConfigAttribute ca = new SecurityConfig((String) resourceRole.get("CODE"));
String url = (String) resourceRole.get("PATH");
if (resourceMap.containsKey(url)) {
Collection<ConfigAttribute> value = resourceMap.get(url);
value.add(ca);
resourceMap.put(url, value);
} else {
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
atts.add(ca);
resourceMap.put(url, atts);
}
}
}

/* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#getAttributes(java.lang.Object)
*/
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
// object 是一个URL,被用户请求的url。
String url = ((FilterInvocation) object).getRequestUrl();

int firstQuestionMarkIndex = url.indexOf("?");
if (firstQuestionMarkIndex != -1) {
url = url.substring(0, firstQuestionMarkIndex);
}
Iterator<String> ite = resourceMap.keySet().iterator();
AntPathMatcher matcher = new AntPathMatcher();
matcher.setTrimTokens(false);
while (ite.hasNext()) {
String resURL = ite.next();
if (matcher.match(resURL, url)) {
logger.info("资源配置URL为"+resURL+"请求的URL为:"+url);
return resourceMap.get(resURL);
}
}
return null;
}

/* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#getAllConfigAttributes()
*/
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.springframework.security.access.SecurityMetadataSource#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}

}


MyUserDetailsService

package com.maven.security;

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

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.maven.auth.dao.UserDao;
import com.maven.auth.entity.Role;
import com.maven.auth.entity.User;

@Transactional
@Service("myUserDetailsService")
public class MyUserDetailsService implements UserDetailsService{

@Autowired
private UserDao userDao;

/* (non-Javadoc)
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userDao.findByUsername(username);
if(user==null) {
throw new UsernameNotFoundException("用户"+username+"不存在!");
}
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
List<Role> roles = user.getRoles();
for(Role role:roles) {
authorities.add(new SimpleGrantedAuthority(role.getCode()));
}
UserDetails userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities);
return userDetails;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring security