007Spring Security
01、基于Spring AOP 和 Servlet规范中Filter实现 的安全框架
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.3.BUILD-SNAPSHOT</version>
</dependency>
02、在Web请求级别 & 方法调用级别 处理身份认证和授权
03、Spring Security配置
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(WebSecurity webSecurity){
//配置Spring Security的Filter链
}
@Override
protected void configure(HttpSecurity httpSecurity){
//配置如何通过拦截器保护
}
@protected void configure(AuthenticationManagerBuilder auth){
//配置user-detail服务
}
}
04、配置user-detail服务
内存存储
@Override
protected void configure(AuthenticationManagerBuilder auth){
auth.inMemoryAuthenticatioin()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");//roles("USER")==authorities("ROLE_USER"),roles会加ROLE_前缀
}
accountExpired(boolean) 定义账号是已否过期
accountLocked(boolean) 是否已锁定
and() 连接配置
authorities(String ...) 给用户授权
credentialsExpired(boolean) 定义凭证是否已过期
disabled(boolean) 定义账号是否被禁用
password(String) 定义用户密码
roles(String ...) 给用户授权
数据库表查询
@Autowired
DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.passwordEncoder(new StandardPasswordEncoder("53cr3t"));
}
数据库中须存在如下5张表
users : username, password, enabled
authorities : username, authority
groups : id, group_name
group_members : group_id, username
group_authorities : group_id, authority
05、加密模块
接口:
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
}
3个实现:
BCryptPasswordEncoder---->uses the BCrypt strong hashing function,推荐加密算法
NoOpPasswordEncoder---->未做任何加密
StandardPasswordEncoder---->uses SHA-256 hashing with 1024 iterations and a random 8-byte random salt value
06、细粒度安全控制---->将最具体的规则放在上面
重载configure(HttpSecurity)方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/spitters/me").authenticated()---->ant风格
.antMatchers(HttpMethed.POST, "/spittles").authenticated()
.antMatchers("/spitters/admin").hasAuthority("ROLE_SPITTER")---->有ROLE_SPITTER权限的用户可访问
.antMatchers("/spitters/user").hasRoles("SPITTER")---->有ROLE_SPITTER权限的用户可访问
.regexMatcher("/spitters/.*").authenticated()---->正则表达式
.anyRequest().permitAll();---->其它请求不需要认证
}
authenticated()---->允许认证过的用户访问。否则,Spring Filter将捕获此请求,并重定向到登陆页面
permitAll()---->无条件允许访问
access(String)---->给定SpEL表达式为true,则允许访问
anonymous()---->允许匿名访问
denyAll()---->无条件拒绝所有访问
fullyAuthenticated()---->用户是完整认证(不是通过Remember-me功能认证),就允许访问
hasAnyAuthority(String ...)---->用户具备给定权限中一个,则允许访问
hasAnyRole(String ...)---->用户具备给定角色中一个,则允许访问
hasAuthority(String)---->用户具备给定权限,则允许访问
hasIpAddress(String)---->请求来自给定IP,则允许访问
hasRole(String)---->用户具备给定角色,则允许访问
not()---->对其它访问方法结果取反
rememberMe()---->用户通过Remember-me功能认证,则允许访问
07、access(String SpEL)安全策略
Spring Security扩展了SpEL语言
authentication 用户认证的对象
denyAll 结果始终为false
hasAnyRole(list of roles) 用户被授予任一指定角色,则为true
hasRole(role) 用户被授予指定角色,则为true
hasIpAddress(IP Address) 请求来之指定IP,则为true
isAnonymous() 当前用户为匿名用户,则true
isAuthenticated() 当前用户已经认证,则true
isFullyAuthenticated() 完整认证
isRememberMe() Remember-me认证
permitAll 始终true
principal 用户的principal对象
antMatchers("/spitter/me").access("hasRole('ROLE_SPITTER') and hasIpAddress('192.168.1.2')")
08、HTTP & Https
表单提交,应该用加密通道
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/spitter/me").hasRole("SPITTER")
.anyRequest().permitAll()
.and()
.requiresChannel()
.antMatchers("/spitter/form").requiresSecure();---->须要https通道。若为http通道请求,将自动重定向到https通道
}
网页首页,不该用加密通道
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/spitter/me").hasRole("SPITTER")
.anyRequest().permitAll()
.and()
.requiresChannel()
.antMatchers("/").requiresInSecure();---->须要http通道。
}
08、HTTP Basic Authentication
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login")
.and()
.httpBasic().realmName("Spittr")---->启用 HTTP Basic 认证
.and()...
}
09、Remember-me功能
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login")
.and()
.rememberMe().tokenValiditySeconds(2419200).key("spittrKey");
}
默认情况下,此功能通过cookie中存储token实现,默认2周有效。此处指定4周有效。
token包含用户名、密码、过期时间、一个私钥,均MD5哈希。
默认私钥名"SpringSecured", 将其设置为"spitterKey",使之专用于Spittr应用。
登陆请求添加remember-me复选框
<input id = "remember_me" name = "remember-me" type = "checkbox"/>
10、logout
默认logout通过Servlet中LogoutFilter实现,此Filter拦截对/logout的请求,退出后,重定向到"/login?logout"
logout时,所有Remember-me token都会被清除。
更改默认配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login")
.and()
.logout().logoutSuccessUrl("/")---->成功退出后重定向到/
.logoutUrl("/signout");---->LoginoutFilter拦截路径
}
11、保护方法安全
配置
@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true, prePostEnabled=true)---->将创建一个切点,Spring Security切面会包装带@Secured注解的方法。
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
...
}
@Secured
@Secured({SROLE_SPITTER", "ROLE_ADMIN"})---->参数为权限数组,调用者必须具备其中一个权限
public void addSpittle(Spittle spittle){
...
}
@PreAuthrize---->方法调用前验证权限
@PreAuthrize("hasRole('ROLE_SPITTER') and #spittle.text.length() <= 140 or hasRole('ROLE_PREMIUM')")
public void addSpittle(Spittle spittle){
...
}
@PostAuthrize---->方法调用后验证权限,主要用于验证返回值
@PostAuthrize("returnObject.spitter.username == principal.username")---->returnObject为返回值对象,principal为当前认证用户主要信息
public Spittle getSpittleById(long id){
...
}
@PostFilter---->返回值过滤
@PostAuthrize("hasAnyRole({'ROLE_SPITTER', 'ROLE_ADMIN'})")
@PostFilter("hasRole('ROLE_ADMIN') || filterObject.spitter.username == principal.name")
public List<Spittle> getOffensiveSpittles(){---->若非admin用户,只能看到自己的spitter }
@PreFilter---->参数过滤
@PreAuthorize("hasAnyRole({'ROLE_SPITTER', 'ROLE_ADMIN'})")
@PreFilter("hasRole('ROLE_ADMIN') || targetObject.spitter.username == principal.name")
public void deleteSpittles(List<Spittle> spittles){
...
}
定义许可计算器
配置:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true, prePostEnabled=true)---->将创建一个切点,Spring Security切面会包装带@Secured注解的方法。
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler(){
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new SpittlePermissionEvaluator());
return expressionHandler;
}
}
hasPermission()许可计算器:
public class SpittlePermissionEvaluator implements PermissionEvaluator {
private static final GrantedAuthority ADMIN_AUTHORITY = new GrantedAuthorityImpl("ROLE_ADMIN"); public boolean hasPermission(Authentication authentication, Object target, Object permission){
if(target instanceof Spittle){
Spittle spittle = (Spittle) target;
String username = spittle.getSpitter().getUsername();
if("delete".equals(permission)){
return isAdmin(authentication) || username.equals(authentication.getName());
}
}
String exp = String.format("hasPermission not supported for object <%s> and permission <%s>", object, permission);
throws new UnsupportedOperationException(exp);
} public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission){
throws new UnsupportedOperationException();
}
private boolean isAdmin(Authentication authentication){
return authentication.getAuthorities().contains(ADMIN_AUTHORITY);
}
}
使用hasPermission()许可计算器:
@PreAuthorize("hasAnyRole({'ROLE_SPITTER', 'ROLE_ADMIN'})")
@PreFilter("hasPermission(targetObject, 'delete')")
public void deleteSpittles(List<Spittle> spittles){
...
}
定义许可计算器
007Spring Security的更多相关文章
- Security Policy:行级安全(Row-Level Security)
行级安全RLS(Row-Level Security)是在数据行级别上控制用户的访问,控制用户只能访问数据库表的特定数据行.断言是逻辑表达式,在SQL Server 2016中,RLS是基于安全断言( ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- Spring Security OAuth2 开发指南
官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. 转载请注明来源:htt ...
- WCF : 修复 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service 问题
摘要 : 最近遇到了一个奇怪的 WCF 安全配置问题, WCF Service 上面配置了Windows Authentication. IIS上也启用了 Windows Authentication ...
- .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
.Net中我们通常使用Random类生成随机数,在一些场景下,我却发现Random生成的随机数并不可靠,在下面的例子中我们通过循环随机生成10个随机数: ; i < ; i++) { Rando ...
- SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...
- spring mvc 和spring security配置 spring-servlet.xml和spring-security.xml设置
spring-servlet.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...
- spring mvc 和spring security配置 web.xml设置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmln ...
- 无法解决“Microsoft.SharePoint.Security, Version=15.0.0.0,”与“Microsoft.SharePoint.Security, Version=14.0.0.0”之间的冲突
VisualStudio 2013创建控制台项目,.NetFramework选为4.5.生成目标平台:x64.然后添加对Microsoft.SharePoint.dll的引用. 生成项目时," ...
随机推荐
- 题目1002:Grading(简单判断)
问题来源 http://ac.jobdu.com/problem.php?pid=1002 问题描述 题目背景为高考试卷批改打分制度.对于每一道题,至少需要两位评审老师进行打分, 当两个老师的打分结果 ...
- Python turtle库学习笔记
1.简介 Python的turtle库的易操作,对初学者十分友好.对于初学者来说,刚学编程没多久可以写出许多有趣的可视化东西,这是对学习编程极大的鼓舞,可以树立对编程学习的信心.当然turtle本身也 ...
- Tree-AC训练实录
Tree-AC比赛记录 2018 ICPC nanjing Bronze 120/310 ICPC qingdao Bronze 153/360 2019 ZJPSC ...
- PHP常见缓存机制
PHP常用的几种缓存机制_PHP教程 普遍缓存技术 数据缓存:这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据, ...
- Kali/Ubuntu无法和物理机之间复制粘贴解决办法
Vmware安装Linux,传统的vmtools已经被抛弃,当前建议使用Open-VM-tools 安装Open-VM-tools//Kali,Ubuntu: sudo apt install Ope ...
- (转)MySQL 主从复制搭建,基于日志(binlog
原文:http://blog.jobbole.com/110934/ 什么是MySQL主从复制 简单来说,就是保证主SQL(Master)和从SQL(Slave)的数据是一致性的,向Master插入数 ...
- Javascript之in操作符的用法
in操作符是js里面常用的一个操作符,下面是其几个常用的功能: 1.配合for语句循环遍历/迭代数组中的元素 2.配合for语句循环遍历/迭代集合中的属性 3.判断对象是否是数组的元素 4.判断对象是 ...
- PHP 对目录下所有TXT进行遍历 并正则进行处理 preg_replace
<?php set_time_limit(); //遍历 指定目录下的所有 文件/ $pattern是要匹配的 文件规则 function file_list($dir,$pattern=&qu ...
- PHP 对字符串 进行填充
1.str_pad — 使用另一个字符串填充字符串为指定长度 . 我觉得str_pad可以满足普通的数字,字符串的简单填充. string str_pad ( string $input , int ...
- Scanner类中的nextToken()方法解读
下面看一下nextToken()方法的源码实现. 1.Java中的控制字符 case ' ': // (Spec 3.6) case '\t': // (Spec 3.6) case FF: // ( ...