最近公司要做开发平台,对安全要求比较高;SPRING SECURTIY框架刚好对所有安全问题都有涉及,框架的作者最近还做了spring-session项目实现分布式会话管理,还有他的另一个开源项目spring-security-oauth2。
关于spring-security的配置方法,网上有非常多的介绍,大都是基于XML配置,配置项目非常多,阅读和扩展都不方便。其实spring-security也有基于java的配置方式,今天就讲讲如何通过java配置方式,扩展spring-security实现权限配置全部从表中读取。
直接上代码:
application.properties配置文件
privilesByUsernameQuery= select authority from user_authorities where username = ?
allUrlAuthoritiesQuery=SELECT authority_id , url FROM Url_Authorities
javaconfig
/**
*
*/
package com.sivalabs.springapp.config;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.util.StringUtils;
import com.sivalabs.springapp.entities.UrlAuthority;
import com.sivalabs.springapp.repositories.UserRepository;
/**
* @author tony
*
*/
@Configuration
@EnableWebSecurity(debug = true)
// @EnableGlobalMethodSecurity(prePostEnabled = true)
// @ImportResource("classpath:applicationContext-security.xml")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
JdbcTemplate jdbcTemplate ;
@Autowired
private Environment env;
@Bean
CustomUserDetailsService customUserDetailsService() {
//==================application.properties文件中配置2个SQL=============
//privilesByUsernameQuery= select authority from user_authorities where username = ?
//allUrlAuthoritiesQuery=SELECT authority_id , url FROM Url_Authorities
String privilesByUsernameQuery = env.getProperty("privilesByUsernameQuery");
String allUrlAuthoritiesQuery = env.getProperty("allUrlAuthoritiesQuery");
CustomUserDetailsService customUserDetailsService = new CustomUserDetailsService();
customUserDetailsService.setJdbcTemplate(jdbcTemplate);
customUserDetailsService.setEnableGroups(false);
//根据登录ID,查登录用户的所有权限
if(StringUtils.hasLength(privilesByUsernameQuery))
customUserDetailsService.setAuthoritiesByUsernameQuery(privilesByUsernameQuery);
//所有URL与权限的对应关系
if(StringUtils.hasLength(privilesByUsernameQuery))
customUserDetailsService.setAllUrlAuthoritiesQuery(allUrlAuthoritiesQuery);
return customUserDetailsService;
}
@Resource(name = "userRepository")
private UserRepository userRepository;
@Override
protected void configure(AuthenticationManagerBuilder registry)
throws Exception {
/*
* registry .inMemoryAuthentication() .withUser("siva") // #1
* .password("siva") .roles("USER") .and() .withUser("admin") // #2
* .password("admin") .roles("ADMIN","USER");
*/
// registry.jdbcAuthentication().dataSource(dataSource);
registry.userDetailsService(customUserDetailsService());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**"); // #3web
}
// AntPathRequestMatcher --> AntPathRequestMatcher --->AntPathMatcher
@Override
protected void configure(HttpSecurity http) throws Exception {
//1.登录注册等URL不要身份验证
http.csrf().disable().authorizeRequests()
.antMatchers("/login", "/login/form**", "/register", "/logout")
.permitAll() // #4
.antMatchers("/admin", "/admin/**").hasRole("ADMIN"); // #6
//2. 从数据库中读取所有需要权限控制的URL资源,注意当新增URL控制时,需要重启服务
List<UrlAuthority> urlAuthorities = customUserDetailsService().loadUrlAuthorities();
for (UrlAuthority urlAuthority : urlAuthorities) {
http.authorizeRequests().antMatchers(urlAuthority.getUrl()).hasAuthority(String.valueOf(urlAuthority.getId()));
}
//3. 除1,2两个步骤验证之外的URL资源,只要身份认证即可访问
http.authorizeRequests().anyRequest().authenticated() // 7
.and().formLogin() // #8
.loginPage("/login/form") // #9
.loginProcessingUrl("/login").defaultSuccessUrl("/welcome") // #defaultSuccessUrl
.failureUrl("/login/form?error").permitAll(); // #5
}
}
1.读取数据库中的URL资源对应的权限列表
2.读取登录用户拥有的权限列表
/**
*
*/
package com.sivalabs.springapp.config;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
import com.sivalabs.springapp.entities.UrlAuthority;
/**
* @author tony
*
*/
public class CustomUserDetailsService extends JdbcDaoImpl{
private String allUrlAuthoritiesQuery ;
/**
* 从数据库中读取所有需要权限控制的URL资源,注意当新增URL控制时,需要重启服务
*/
public List<UrlAuthority> loadUrlAuthorities( ) {
return getJdbcTemplate().query(allUrlAuthoritiesQuery, new RowMapper<UrlAuthority>() {
public UrlAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
return new UrlAuthority (rs.getInt(1),rs.getString(2));
}
});
}
/**
* 从数据库中读取用户权限
* Loads authorities by executing the SQL from <tt>authoritiesByUsernameQuery</tt>.
* @return a list of GrantedAuthority objects for the user
*/
protected List<GrantedAuthority> loadUserAuthorities(String username) {
return getJdbcTemplate().query(super.getAuthoritiesByUsernameQuery(), new String[] {username}, new RowMapper<GrantedAuthority>() {
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
String roleName = rs.getString(1);
return new SimpleGrantedAuthority(roleName);
}
});
}
public void setAllUrlAuthoritiesQuery(String allUrlAuthoritiesQuery) {
this.allUrlAuthoritiesQuery = allUrlAuthoritiesQuery;
}
}
测试数据及案例见
http://note.youdao.com/share/?id=c20e348d9a08504cd3ac1c7c58d1026e&type=note
spring-security-oauth2
http://www.mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2
Maven Repository: org.springframework.session » spring-session
http://www.mvnrepository.com/artifact/org.springframework.session/spring-session