源码地址:demo-world (spring-sercurity模块) 目录 前几期我们了解了Spring Security Authentication (认证),今天我们来说道说道 Spring Security Authorization(授权) 这里举一个通俗易懂的例子:你去火车站买票乘车,你需要两样东西,身份证和车票,在去月台之前,你需要刷一下身份证,确认你是本人,这就是认证,当你坐上了火车,这时候列车员回来检查你的车票,来确定你是否可以做这一班车,这就是授权 首先我们来回顾一下 认证的结果: 也就是Authentication中的内容,我们来逐一分析一下: 可以从Authentication.getAuthorities()方法获得GrantedAuthoritys。此方法提供了GrantedAuthority对象的集合。GrantedAuthority是授予用户的权限。GrantedAuthority通常由UserDetailsService加载。 此类权限通常有两种: Spring Security包含一个具体的GrantedAuthority实现,即SimpleGrantedAuthority。它允许将任何用户指定的String转换为GrantedAuthority。安全体系结构中包含的所有AuthenticationProvider都使用SimpleGrantedAuthority来填充Authentication对象。 AccessDecisionManager 由 AbstractSecurityInterceptor 调用,并负责做出最终的访问控制决策。 AccessDecisionManager接口包含三种方法: decide方法的参数包括它进行授权决策所需的所有相关信息。secureObject是安全对象,也就是我要保护的访问资源,例如 method authorization(方法授权)中方法就是受保护的资源,然后在AccessDecisionManager中实现某种安全性逻辑以确保安全访问。如果访问被拒绝,则预期实现将引发AccessDeniedException。 在启动时,AbstractSecurityInterceptor将调用support(ConfigAttribute)方法,以确定AccessDecisionManager是否可以处理传递的ConfigAttribute。安全拦截器实现调用support(Class)方法,以确保配置的AccessDecisionManager支持安全拦截器将显示的安全对象的类型。 首先,GrantedAuthority通常由UserDetailsService加载的,因此,我们使用SimpleGrantedAuthority来简单为用户分配一个角色 首先我们来改造一下我们的UserDO,增加一个权限集合字段: 然后我们将回到UserDetails的配置中来,实现该接口的方法: 我们还需要修改一下伪数据源 验证我们配置的结果: OK!成功给用户分配了角色,角色也是权限的集合,一个角色可以拥有很多权限,例如实习生可以查看文件和修改文件(两个权限),但不可以增加文件和删除文件,那么Spring是如何做到这一点的呢?答案就在 AccessDecisionManager 中,顾名思义,这是访问决策中心,一个访问是否被允许,就是由此类决定的 Spring Security提供了拦截器,用于控制对安全对象的访问,例如方法调用或Web请求。 AccessDecisionManager会做出关于是否允许进行调用的调用前决定。 FilterSecurityInterceptor为HttpServletRequests提供授权。它作为安全筛选器之一插入到FilterChainProxy中,要注意不要被名字迷惑,它不是拦截器,是过滤器 First, the Second, Next, it passes the Finally, it passes the If authorization is denied, an If access is granted, 默认情况下,Spring Security 将会对所有的请求进行身份认证,如下: 也可以自定义认证规则,如下: 这里有几个很重要的点要注意一下: 这里由一张由官方提供的内置表达式表格: Returns For example, By default if the supplied role does not start with ‘ROLE_’ it will be added. This can be customized by modifying the Returns For example, By default if the supplied role does not start with ‘ROLE_’ it will be added. This can be customized by modifying the Returns For example, Returns For example, Allows direct access to the principal object representing the current user Allows direct access to the current Always evaluates to Always evaluates to Returns Returns Returns Returns Returns Returns 上面我们使用了Role来控制某个用户是否可以访问一个接口(或handler 方法),但很明显,在实际开发中,这样使用会有很多局限性,例如对用户是否有权访问某一个接口的判断过程很复杂,那么,这种直接在HttpSecurity中配置的方法,显然就不太实用了,因此需要使用基于 Handler 方法的权限控制,Spring为我们提供了几个很有用的注解 要使用注解,首先在SecurityConfig中开启它 这是一个很实用的注解,它可以决定方法是否可以被调用,如下: 这种写法和之前我们配置的作用相同,当然此注解还有更强大的地方,例如还可以这么写(表示只有id =2才可以访问): 不过,大部分时候这些功能还是不能满足我们的需求,所以该注解还支持注入Bean,和自定义权限认证,我们来写一个简单的例子: 以上代码表示,只有用户名为swing的用户才能访问此接口
1.简介
2.GrantedAuthority
GrantedAuthority
s are high level permissions the user is granted. A few examples are roles or scopes.
3.AccessDecisionManager
void decide(Authentication authentication, Object secureObject, Collection<ConfigAttribute> attrs) throws AccessDeniedException; boolean supports(ConfigAttribute attribute); boolean supports(Class clazz);
4.角色(role)
/** * 权限集合 */ Set<GrantedAuthority> authorities;
/** * 返回授予用户的权限 * * @return 权限集合 */ @Override public Collection<? extends GrantedAuthority> getAuthorities() { return userDO.getAuthorities(); }
public class DataSource { public static UserDO getUserByUsername(String username) { SimpleGrantedAuthority roleIntern = new SimpleGrantedAuthority("ROLE_INTERN"); SimpleGrantedAuthority roleDba = new SimpleGrantedAuthority("ROLE_DBA"); SimpleGrantedAuthority roleAdmin = new SimpleGrantedAuthority("ROLE_ADMIN"); List<UserDO> userList = new ArrayList<>(); //初始化三个用户 userList.add(new UserDO(1L, "swing", new BCryptPasswordEncoder().encode("123456"), 20, Arrays.asList(roleDba, roleIntern))); userList.add(new UserDO(2L, "sky", new BCryptPasswordEncoder().encode("123456"), 20, Collections.singletonList(roleIntern))); userList.add(new UserDO(3L, "admin", new BCryptPasswordEncoder().encode("123456"), 20, Arrays.asList(roleDba, roleIntern, roleAdmin))); return userList.stream().distinct().filter(userDO -> userDO.getUsername().equals(username)).collect(Collectors.toList()).get(0); } }
5.FilterSecurityInterceptor
FilterSecurityInterceptor
obtains an Authentication from the SecurityContextHolder.FilterSecurityInterceptor
creates a FilterInvocation
from the HttpServletRequest
, HttpServletResponse
, and FilterChain
that are passed into the FilterSecurityInterceptor
.FilterInvocation
to SecurityMetadataSource
to get the ConfigAttribute
s.Authentication
, FilterInvocation
, and ConfigAttribute
s to the AccessDecisionManager
.
AccessDeniedException
is thrown. In this case the ExceptionTranslationFilter
handles the AccessDeniedException
.FilterSecurityInterceptor
continues with the FilterChain which allows the application to process normally.
protected void configure(HttpSecurity http) throws Exception { http // ... .authorizeRequests(authorize -> authorize .anyRequest().authenticated() ); }
@Override protected void configure(HttpSecurity http) throws Exception { //禁用csrf (跨站请求伪造) http.csrf().disable(); http.authorizeRequests(authorize -> authorize //允许直接访问 .mvcMatchers("/login").permitAll() .mvcMatchers("/file/1/**").hasRole("INTERN") .mvcMatchers("/file/4/**").hasRole("ADMIN") //同时具有两种角色才可访问的api .mvcMatchers("/login/page").access("hasRole('INTERN') and hasRole('DBA')") //剩下的都拒绝 .anyRequest().denyAll() ); //将认证设置在UsernamePasswordAuthenticationFilter之前 http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class); }
Expression
Description
hasRole(String role)
true
if the current principal has the specified role.hasRole('admin')
defaultRolePrefix
on DefaultWebSecurityExpressionHandler
.
hasAnyRole(String… roles)
true
if the current principal has any of the supplied roles (given as a comma-separated list of strings).hasAnyRole('admin', 'user')
defaultRolePrefix
on DefaultWebSecurityExpressionHandler
.
hasAuthority(String authority)
true
if the current principal has the specified authority.hasAuthority('read')
hasAnyAuthority(String… authorities)
true
if the current principal has any of the supplied authorities (given as a comma-separated list of strings)hasAnyAuthority('read', 'write')
principal
authentication
Authentication
object obtained from the SecurityContext
permitAll
true
denyAll
false
isAnonymous()
true
if the current principal is an anonymous user
isRememberMe()
true
if the current principal is a remember-me user
isAuthenticated()
true
if the user is not anonymous
isFullyAuthenticated()
true
if the user is not an anonymous or a remember-me user
hasPermission(Object target, Object permission)
true
if the user has access to the provided target for the given permission. For example, hasPermission(domainObject, 'read')
hasPermission(Object targetId, String targetType, Object permission)
true
if the user has access to the provided target for the given permission. For example, hasPermission(1, 'com.example.domain.Message', 'read')
6.基于Handler方法的权限控制
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
6.1.@PreAuthorize
/** * 获取登录页面 * * @return 登录页面 */ @PreAuthorize("hasRole('INTERN') and hasRole('DBA')") @GetMapping("/page") String login() { return "login"; }
@PreAuthorize("hasRole('INTERN') and #id==2") @GetMapping("/1/{id}") @ResponseBody public FileDO getFileNameById(@PathVariable Long id) { return new FileDO(id, "这个杀手不太冷.mp4", 1231232423L); }
/** * 自定义认证方法 * * @author swing */ @Service("as") public class AuthorizeService { /** * 是否授权 * * @return 是否可以访问呢 */ public boolean hasPermission(String username) { UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); return userDetails.getUsername().equals(username); } }
/** * 获取文件 * * @param id 文件Id * @return 文件信息 */ @PreAuthorize("@as.hasPermission('swing')") @GetMapping("/1/{id}") @ResponseBody public FileDO getFileNameById(@PathVariable Long id) { return new FileDO(id, "这个杀手不太冷.mp4", 1231232423L); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算