栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

oauth2 密码模式和授权模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

oauth2 密码模式和授权模式

https://blog.csdn.net/feinifi/article/details/108123831

笔记部分

oauth2实验

  • pom

    • 
          org.springframework.boot
          spring-boot-starter-security
      
      
  • 当用户安装了上面maven就自己打开了验证功能,密码可以再login打开

  • @EnableWebSecurity和extends WebSecurityConfigurerAdapter即可自己配置securiyt的验证;

    • public UserDetailsService userDetailsService()可以配置验证的账号和密码和权限
    • public PasswordEncoder passwordEncoder()和上面搭配使用,密码加密功能,必须要,这个和上面已经可以正常使用登录验证功能了
    • protected void configure(HttpSecurity http) throws Exception这个是用来对http请求进行过滤使用的
      • hasAuthority("p1") 需要权限
      • authenticated()需要验证
      • permitAll()不需要验证
  • 工作原理

  • 用户提交用户名、密码被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 过滤器获取到, 封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。

  • 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证

    • 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息, 身份信息,细节信息,但密码通常会被移除) Authentication 实例。

    • SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过 SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。 可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它 的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个 List 列表,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终AuthenticationProvider将UserDetails填充至Authentication

  • UserDetailsService 这个只能作为方法,或者被继承,二选一,而不能共存

  • http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)

    • always如果没有session存在就创建一个
      ifRequired如果需要就创建一个Session(默认)登录时
      neverSpringSecurity 将不会创建Session,但是如果应用中其他地方创建了Session,那么Spring
      statelessSecurity将会使用它。SpringSecurity将绝对不会创建Session,也不使用Session
    • 若使用stateless,则说明Spring Security对登录成功的用户不会创建Session了,你的应用程序也不会允许新建 session。并且它会暗示不使用cookie,所以每个请求都需要重新进行身份验证。这种无状态架构适用于REST API 及其无状态认证机制。

    • 我们可以使用httpOnly和secure标签来保护我们的会话cookie:

      • httpOnly:如果为true,那么浏览器脚本将无法访问cookie
      • secure:如果为true,则cookie将仅通过HTTPS连接发送

验证加oauth2

  • pom

    • 
          org.springframework.boot
          spring-boot-starter-security
      
      
      
          org.springframework.security.oauth
          spring-security-oauth2
          2.3.4.RELEASE
      
      

-

  • 1、根据用户名密码等参数直接获取token
    接口:http://localhost:8080/oauth/token
    参数:username password grant_type client_id client_secret redirect_uri
    返回值:access_token
    2、根据token,访问资源
    接口:http://localhost:8080/api/test/hello
    参数:access_token
  • 认证服务器配置(0)>资源服务器配置(3)>web安全服务配置(100)
  • httpBasic 和 formLogin
    • httpBasic 是http认证协议Basic auth 验证才可以访问,或者在请求头加上Authorization:Basic 加密后用户名:密码
    • formLogin 使用表单验证,采用post方法,也可以退出登录.
    • httpBasic 是没有login接口系列,要自主加上formLogin方法才有
    • httpBasic 适合只有http请求,formLogin适合有web页面展示,就是后台管理,可以同时存在
  • 授权 自家app myapp 别家app otherapp 都是别人想要我的其中一个服务,hello
    • 授权码模式
      • otherapp 带上请求,访问myapp
      • http://myappurl/oauth/authorize?response_type=code(授权模式)&state=123456(非必须)&client_id=client(客户端id)&scope=all(请求范围)&redirect_uri=http://otherappurl
      • 返回http://otherappurl?code=ycjU3F&state=123456可以拿到ycjU3F这个code
      • 然后请求http://myappurl/oauth/token?client_id=client(客户端id)&client_secret=secret(密钥)&grant_type=authorization_code(在clients中定义)&code=ycjU3F&redirect_uri=http://otherappurl这个请求可以是post也可以是get然后会返回
      • {
        “access_token”: “2311e499-bd15-4eee-a718-0edb113e71ef”,
        “token_type”: “bearer”,
        “refresh_token”: “b920b1ad-1083-428a-9762-fe549e358fee”,
        “expires_in”: 1171,
        “scope”: “all”
        }
      • 将参数带上请求可以访问的地方http://myapp?access_token=2311e499-bd15-4eee-a718-0edb113e71ef必须有权限才行
    • 密码模式
      • 与上面的授权码模式唯一不同就是需要改变grant_type,减去code,然后加上username和password参数即可http://myother/oauth/token?client_id=client&client_secret=secret&grant_type=password&redirect_uri=http://example.com&username=admin&password=123
代码部分

web配置

@EnableWebSecurity
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        inMemoryUserDetailsManager.createUser(User.withUsername("admin").password(passwordEncoder().encode("123")).roles("admin").build());
        inMemoryUserDetailsManager.createUser(User.withUsername("user").password(passwordEncoder().encode("123")).roles("user").build());
        return inMemoryUserDetailsManager;
    }
    

    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //使用basic加密 需要在请求头加上Authorization: Basic 加密后的username:password
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/oauth
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @PostConstruct
    public void init(){
        // System.out.println("123密码加密后密码  ↓↓↓↓↓ ");
        // System.out.println(passwordEncoder().encode("123"));
    }
}

资源服务

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/admin
@Configuration
@EnableAuthorizationServer
public class AuthServerConfiguration  extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 密码模式下配置认证管理器 AuthenticationManager
        endpoints.authenticationManager(authenticationManager);
        endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
    }
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.realm("oauth2-resources")
                // 开启/oauth/token_key验证端口无权限访问
                .tokenKeyAccess("permitAll()")
                // 开启/oauth/check_token验证端口认证权限访问
                .checkTokenAccess("isAuthenticated()")
                // 允许客户表单认证
                .allowFormAuthenticationForClients();
    }
    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                // client_id
                .withClient("client")
                // client_secret
                .secret(passwordEncoder.encode("secret"))
                .redirectUris("http://example.com")
                // 授权类型
                .authorizedGrantTypes("authorization_code","password","refresh_token","implicit","client_credentials")
                // 授权范围
                .scopes("all")
                // 登录后绕过批准询问(/oauth//confirm/i_access)
                .autoApprove(true)
                .resourceIds("oauth2-resource")
                .accessTokenValiditySeconds(1200)
                .refreshTokenValiditySeconds(50000);
    }
}

用户连接数据库

@Service
public class SpringDataUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //登录账号
         System.out.println("username="+username);
        //根据账号去数据库查询...
        // 这里暂时使用静态数据
         UserDetails userDetails = User.withUsername(username).password("123").authorities("p1").build();
         return userDetails;
    }
}
public void configure(HttpSecurity http)

如果哪个过滤器匹配到url,下个过滤器就会失效
antMatchers 匹配一个或者多个请求
anyRequest 匹配剩下所有请求
antMatcher()和authorizeRequests().antMatchers()。----表示此过滤器,只拦截一个或者多个并且验证.
permitAll(). ---- 放行
.anyRequest().authenticated()----请求会被其他过滤器拦截

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/591374.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号