oauth2-怎么使用

1.权限模型RBAC模型

迄今为止最为普及的权限设计模型是 RBAC 模型, 基于角色的访问控制(Role-Based Access Control)
在这里插入图片描述

2.使用框架

  1. shiro
  2. spring security

3.spring security 如何使用

1. WebSecurityConfigurerAdapter
@Configuration
// 启用spring security
@EnableWebSecurity(debug = true)
//启用方法注解 例如 @PreAuthorize和@PostAuthorize
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 设置默认的加密方式
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    // 配置用户认证
    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl();
    }
    // 认证模块
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    // 授权
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 禁用csrf 防止csrf攻击
        http.csrf().disable();
        http
                // 配置登录信息
                .logout()
                .logoutUrl("/logout").logoutSuccessUrl("/")
                .and()
                // 配置授权信息
                .authorizeRequests()
                .mvcMatchers( "/login","/login/**", "/assets/**")
                .permitAll()
                .anyRequest()
                // 配置匿名登录
                .authenticated()
                .and()
                // 配置oauth2 登录
                .oauth2Login()
                .authorizationEndpoint();
        http.oauth2Client().authorizationCodeGrant();
    }

    // 静态资源配忽略
    @Override
    public void configure(WebSecurity web) throws Exception {
       //oauth2 获取公钥配置
        web.ignoring().mvcMatchers("/oauth/token_key", "/oauth/check_token");
    }
}

HttpSecurity 日常的基本配置使用

方法说明
requestMatchers()为 SecurityFilterChain 提供URL拦截策略,具体还提供了 antMatcher 和 mvcMathcer
openidLogin()用于基于 OpenId 的验证
headers()将安全标头添加到响应,比如说简单的 XSS 保护
cors()配置跨域资源共享( CORS )
sessionManagement()配置会话管理
portMapper()配置一个 PortMapper(HttpSecurity#(getSharedObject(class))) ,其他提供 SecurityConfigurer 的对象使用 PortMapper 从 HTTP 重定向到 HTTPS 或者从 HTTPS 重定向到 HTTP。默认情况下,Spring Security使用一个 PortMapperImpl 映射 HTTP 端口8080到 HTTPS 端口8443, HTTP 端口80到 HTTPS 端口443
jee()配置基于容器的预认证。 在这种情况下,认证由Servlet容器管理
x509()配置基于x509的预认证 rememberMe 配置“记住我”的验证
authorizeRequests()基于使用 HttpServletRequest 限制访问
requestCache()配置请求缓存
exceptionHandling()配置错误处理
securityContext()在 HttpServletRequests 之间的 SecurityContextHolder 上设置 SecurityContext 的管理。 当使 用 WebSecurityConfigurerAdapter 时,这将自动应用
servletApi()将 HttpServletRequest 方法与在其上找到的值集成到 SecurityContext 中。 当使用 WebSecurityConfigurerAdapter 时,这将自动应用
csrf()添加 CSRF 支持,使用 WebSecurityConfigurerAdapter 时,默认启用
logout()添加退出登录支持。当使用 WebSecurityConfigurerAdapter 时,这将自动应用。默认情况是,访问 URL”/ logout”,使HTTP Session无效来清除用户,清除已配置的任何#rememberMe()身份验证,清除 SecurityContextHolder ,然后重定向到 /login?success anonymous() 配置匿名用户的表示方法。 当与 WebSecurityConfigurerAdapter 结合使用时,这将自动应用。 默认 情况下,匿名用户将使用 org.springframework.security.authentication.AnonymousAuthenticationToken 表示,并包含 角色 ROLE_ANONYMOUS authenticationManager() 配置 AuthenticationManager
authenticationProvider()添加 AuthenticationProvider
formLogin()指定支持基于表单的身份验证。如果未指定 FormLoginConfigurer#loginPage(String) ,则将生成默 认登录页面
oauth2Login()根据外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份验证
oauth2Client()OAuth2.0 客户端相关的配置
oauth2ResourceServer()OAuth2.0资源服务器相关的配置
requiresChannel()配置通道安全。为了使该配置有用,必须提供至少一个到所需信道的映射
httpBasic()配置 Http Basic 验证
addFilter()添加一个已经在内置过滤器注册表注册过的过滤器实例或者子类
addFilterBefore()在指定的Filter类之前添加过滤器
2.PasswordEncoder 密码校验器(主要用于)
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 设置默认的加密方式
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
3.UserDetailsService 用户信息接口
public interface UserDetailsService {

	根据用户名定位用户。在实际实现中,搜索可能区分大小写,也可能不区分大小写,具体取决于实现实例的配置方式。
	在这种情况下,返回的 <code>UserDetails<code> 对象的用户名可能与实际请求的用户名不同。
	@param username 标识需要其数据的用户的用户名。
	@return 完全填充的用户记录(从不 <code>null<code>@throws UsernameNotFoundException 
	如果找不到用户或用户没有 GrantedAuthority
	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

根据用户名加载用户 UserDetails ,可能抛出用户不存在的异常 security 中 登录用UserDetailsService 去检索个人信息。
项目中的实践如下

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionService permissionService;
    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        // 查询用户信息
        com.template.cloud.oauth.entity.User user = userService.loadUserByUserName(userName);
        List<GrantedAuthority> grantedAuthorities =new ArrayList<>();
        if (user != null) {
            // 获取用户授权
            Set<String> permissions = permissionService.loadPermissionByUserId(user.getId());
            // 声明用户授权
            if(CollUtil.isNotEmpty(permissions)){
                permissions.forEach(permission -> {
                    if (StrUtil.isNotBlank(permission)) {
                        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission);
                        grantedAuthorities.add(grantedAuthority);
                    }
                });
            }
            // 由框架完成认证工作
            return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
        }else {
            return null;
        }
    }
}
4.AuthenticationManager 认证管理器

主要处理认证请求的管理器
主要的实现如下
在这里插入图片描述

5.Authentication 认证信息

Spring Security中抽象了一个认证的概念接口 Authentication 。认证主体的认证信息、状态都
由 Authentication 来负责维护

6.spring security filter 顺序
FilterComparator() {
		Step order = new Step(INITIAL_ORDER, ORDER_STEP);
		put(ChannelProcessingFilter.class, order.next());
		put(ConcurrentSessionFilter.class, order.next());
		put(WebAsyncManagerIntegrationFilter.class, order.next());
		put(SecurityContextPersistenceFilter.class, order.next());
		put(HeaderWriterFilter.class, order.next());
		put(CorsFilter.class, order.next());
		put(CsrfFilter.class, order.next());
		put(LogoutFilter.class, order.next());
		filterToOrder.put(
			"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
				order.next());
		filterToOrder.put(
				"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter",
				order.next());
		put(X509AuthenticationFilter.class, order.next());
		put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
		filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",
				order.next());
		filterToOrder.put(
			"org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
				order.next());
		filterToOrder.put(
				"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter",
				order.next());
		put(UsernamePasswordAuthenticationFilter.class, order.next());
		put(ConcurrentSessionFilter.class, order.next());
		filterToOrder.put(
				"org.springframework.security.openid.OpenIDAuthenticationFilter", order.next());
		put(DefaultLoginPageGeneratingFilter.class, order.next());
		put(DefaultLogoutPageGeneratingFilter.class, order.next());
		put(ConcurrentSessionFilter.class, order.next());
		put(DigestAuthenticationFilter.class, order.next());
		filterToOrder.put(
				"org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter", order.next());
		put(BasicAuthenticationFilter.class, order.next());
		put(RequestCacheAwareFilter.class, order.next());
		put(SecurityContextHolderAwareRequestFilter.class, order.next());
		put(JaasApiIntegrationFilter.class, order.next());
		put(RememberMeAuthenticationFilter.class, order.next());
		put(AnonymousAuthenticationFilter.class, order.next());
		filterToOrder.put(
			"org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter",
				order.next());
		put(SessionManagementFilter.class, order.next());
		put(ExceptionTranslationFilter.class, order.next());
		put(FilterSecurityInterceptor.class, order.next());
		put(SwitchUserFilter.class, order.next());
	}

每个filter 的作用
1、WebAsyncManagerIntegrationFilter:
提供了对securityContext和WebAsyncManager的集成,使其支持把SecurityContext设置基于ThreadLocal的SecurityContextHolder中,使controller中线程安全地获取到用户上下文认证信息。

2、SecurityContextPersistenceFilter
请求到来时,通过HttpSessionSecurityContextRepository接口从Session中读取SecurityContext,如果读取结果为null,则创建之。获得SecurityContext之后,会将其存入SecurityContextHolder,其中SecurityContextHolder默认是ThreadLocalSecurityContextHolderStrategy实例。
请求结束时清空SecurityContextHolder,并将SecurityContext保存到Session中。
3、HeaderWriterFilter
用来给http response添加一些Header,比如X-Frame-Options、X-XSS-Protection*、X-Content-Type-Options。
X-Frame-Options:防止某些重要网页被其他网站框架导入
X-XSS-Protection*:防止XSS攻击
X-Content-Security-Policy:这个响应头主要是用来定义页面可以加载哪些资源,减少XSS的发生
X-Content-Type-Options:互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:text/html、text/css
4、CsrfFilter
防止csrf跨域攻击,伪造表单,要求表单POST提交时带有crsf令牌
5、LogoutFilter
对登出url的请求处理,执行登出操作
6、UsernamePasswordAuthenticationFilter
对登陆url的请求处理,校验用户账号密码,校验成功后执行以下操作:

a. (ConcurrentSessionStrategy)向框架特有的SessionRegistry添加用户和session信息,并管理策略执行用户多点登陆检查,做出对应的‘不予许登陆’或‘令旧会话失效’和‘允许登陆的操作’
b. 在SecurityContext存认证信息
c. 执行rememberme服务,添加cookies
d. 由eventpublisher发布认证事件
e. 结束filter链,登陆成功跳转,执行新一轮的filter链检查(这次时已登陆状态不用再登陆啦)
7、ConcurrentSessionFilter
根据当前sessionID检查SessionRegistry保存的session信息是否过期

过期:则执行登出操作(销毁旧过期session触发session事件从而删除SessionRegistry的信息)跳转到login操作尝试自动登陆,此时一般会由rememberme执行登陆,此时登出操作一般会把rememberme删除,登陆失败,跳转到登陆页,手动登陆
不过期:则刷新访问时间
不存在则跳过
8、RequestCacheAwareFilter
将request存到session中,用于缓存request请求,可以用于恢复被登录而打断的请求
此处从session中取出request,存储request是ExceptionTranslationFilter
9、SecurityContextHolderAwareRequestFilter
此过滤器对ServletRequest进行了一次包装,使得request具有更加丰富的API
10、RememberMeAuthenticationFilter
服务器重启后rememberme失效,默认保存在内存的和SessionRegistry一样需要重新配置
读取客户端的remember的cookies来实现自动登陆,在SecurityContext存认证信息
11、AnonymousAuthenticationFilter
前面都没有成功登陆则执行匿名登陆,在SecurityContext存认证信息
12、SessionManagementFilter
session固化保护-通过session-fixation-protection配置
session并发控制-通过concurrency-control配置 (这个主要在过过滤器6和7执行的)和session相关的过滤器,内部维护了一个SessionAuthenticationStrategy,两者组合使用,常用来防止session-fixation protection attack,以及限制同一用户开启多个会话的数量
与登录认证拦截时作用一样,持久化用户登录信息,可以保存到session中,也可以保存到cookie或者redis中。
13、ExceptionTranslationFilter
异常拦截,其处在Filter链后部分,只能拦截其后面的节点并且只处理AuthenticationException
与AccessDeniedException两个异常。AuthenticationException指的是未登录状态下访问受保护资源,
AccessDeniedException指的是登陆了但是由于权限不足(比如普通用户访问管理员界面)。
14、FilterSecurityInterceptor
这个filter用于授权验证。FilterSecurityInterceptor的工作流程引用一下,可以理解如下:

FilterSecurityInterceptor从SecurityContextHolder中获取Authentication对象,
然后比对用户拥有的权限和资源所需的权限。前者可以通过Authentication对象直接获得,
而后者则需要引入我们之前一直未提到过的两个类:SecurityMetadataSource,AccessDecisionManager。

7.filter 的认证过程

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值