SpringSecurityOAuth开发app认证框架

在这里插入图片描述
在这里插入图片描述
令牌的表现形式就是一个字符串

在这里插入图片描述


实现一个标准的oauth2协议中的provider角色的主要功能
重构之前的认证方式的代码,使其支持token
高级特性

服务提供商的实现

认证服务器
资源服务器

认证服务器

demo pom 文件中引入app模块依赖 使正常启动

      <!--<dependency>-->
            <!--<groupId>com.whale.security</groupId>-->
            <!--<artifactId>whale-security-browser</artifactId>-->
            <!--<version>${whale.security.version}</version>-->
        <!--</dependency>-->

        <dependency>
            <groupId>com.whale.security</groupId>
            <artifactId>whale-security-app</artifactId>
            <version>${whale.security.version}</version>
        </dependency>

注释掉session的配置
重新启动

Message: Error creating bean with name 'validateCodeFilter': Unsatisfied dependency expressed through field 'authenticationFailureHandler'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.web.authentication.AuthenticationFailureHandler' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2019-05-20 13:58:01.564  INFO 11352 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

没有找到失败处理器
因为之前的在browser模块里面
在这里插入图片描述
在app模块里面重新创建失败处理器

先直接把browser里面的这两个失败 成功处理器拷贝到app,并引入相关类
在这里插入图片描述
重新启动

Error creating bean with name 'myUserDetailsService': Unsatisfied dependency expressed through field 'passwordEncoder';

在这里插入图片描述

@Configuration
@EnableConfigurationProperties(SecurityProperties.class)//使SecurityProperties中的配置生效
public class SecurityCoreConfig {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();//也可以自定义 只要实现PasswordEncoder接口
    }
}

再次重新启动

已经正常启动起来

实现认证服务器

在这里插入图片描述

WhaleAuthenticationSecurityConfig
@Configuration
@EnableAuthorizationServer
public class WhaleAuthenticationSecurityConfig {
}

这样就已经实现了一个认证服务器
可以提供oauth的四种授权模式

重新启动
控制台有如下几个路径
在这里插入图片描述
直接访问报错

授权码模式的请求参数

在这里插入图片描述
这还需要一些参数
https://oauth.net/2/
https://tools.ietf.org/html/rfc6749
在这里插入图片描述
查看授权码模式
https://tools.ietf.org/html/rfc6749#page-24
它需要如下几个请求参数
在这里插入图片描述

client_Id 启动的时候会在控制台打印出来
在这里插入图片描述
其中client_id 和 client_secret 每次启动都会自动变化
demo application 配置下

security.oauth2.client.client-id=whale
security.oauth2.client.client-secret=123456

User must be authenticated with Spring Security before authorization can be completed.

构造请求参数重新请求
http://127.0.0.1:8080/oauth/authorize?response_type=code&client_id=whale&redirect_uri=http://example.com&scope=all
报错

org.springframework.security.authentication.InsufficientAuthenticationException: User must be authenticated with Spring Security before authorization can be completed.

根据这个路径找发到这个方法
在这里插入图片描述
AuthorizationEndpoint

	@RequestMapping(value = "/oauth/authorize")
	public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,
			SessionStatus sessionStatus, Principal principal) {

		// Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should
		// query off of the authorization request instead of referring back to the parameters map. The contents of the
		// parameters map will be stored without change in the AuthorizationRequest object once it is created.
		AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);

		try {
		·················································
			if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
				throw new InsufficientAuthenticationException(
						"User must be authenticated with Spring Security before authorization can be completed.");
			}
			················································
		}
		catch (RuntimeException e) {
			sessionStatus.setComplete();
			throw e;
		}

	}

方法里有个if语句,它是判断我们当前有没有登录,我打断点过去发现principal为null

结合错误提示,是想让我们登录

我随便访问一个地址http://localhost:8080/hello 竟然不需要登录,我百思不得题姐

注释掉WhaleAuthenticationSecurityConfig 这个认证服务器的配置类,就又需要登录了

看来原因就是出在这个类上,配置了认证服务器原来的安全认证就失效了吗?

之前项目依赖browser模块时有一个BrowserSecurityConfig继承了WebSecurityConfigurerAdapter
现在依赖app了 我在demo下重新写一个WebSecurityConfigurerAdapter的实现
在这里插入图片描述

MySecurityConfig
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier("demoUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.formLogin()   //指定身份认证的方式为表单登录
                .and()
                .authorizeRequests() //对请求授权
                .anyRequest()        //任何请求
                .authenticated()    //安全认证
        .and().userDetailsService(userDetailsService);
    }
}
DemoUserDetailsService
@Component
public class DemoUserDetailsService implements UserDetailsService{
    // 这里注入dao 层 用于查询数据库

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //根据用户名从数据库查找用户信息
        logger.info("UserDetails 登录用户名"+ userName);
        String password = passwordEncoder.encode("123456");

        return new User(userName, password,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));//第三个参数是做授权的
    }
期间有出现一个错误This application has no explicit mapping for /error, so you are seeing this as a fallback.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

There was an unexpected error (type=Forbidden, status=403).
Access Denied

因为在springboot中所有的类不能和启动类同级

error=“invalid_request”, error_description="At least one redirect_uri must be registered with the client

再次重新启动访问请求连接又报错 也是醉了

OAuth Error
error="invalid_request", error_description="At least one redirect_uri must be registered with the client."

打断点
AuthorizationEndpoint /oauth/authorize里面
在这里插入图片描述
DefaultRedirectResolver
在这里插入图片描述
registeredRedirectUris 为null 所至

解决
https://blog.csdn.net/taotaojs/article/details/85126140 这个不能解决
https://segmentfault.com/q/1010000015995274/a-1020000015998139 ok

其他
https://www.cnblogs.com/cjsblog/p/9296361.html
https://alexbilbie.com/guide-to-oauth-2-grants/
https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/
https://blog.csdn.net/qq_36144258/article/details/79413485
https://blog.csdn.net/u013815546/article/details/76898524
https://segmentfault.com/a/1190000012260914


在demo application中加入
security.oauth2.client.registered-redirect-uri=http://example.com

再次启动 重新访问 成功了

授权码授权流程

在这里插入图片描述

点击授权

在这里插入图片描述

这时已经跳转到第三方应用了

第三方应用应该拿着这个授权码去获取token post 访问 /oauth/token

post 访问 /oauth/token
在这里插入图片描述

先修改MySecurityConfig 的登录方式为 httpBasic()
然后用postman 验证一下
在这里插入图片描述
ok
https://tools.ietf.org/html/rfc6749#page-24
在这里插入图片描述
在这里插入图片描述

/oauth/token的访问

注意请求参数中的code为我们的授权码
在这里插入图片描述
安全认证为
在这里插入图片描述
如下
在这里插入图片描述

{
  "access_token": "7b4c3f66-d3b4-4035-b46c-41a5f1ff0b26",
  "token_type": "bearer",
  "refresh_token": "9e1a166e-492d-4ad7-b9c2-b4bd36336f2a",
  "expires_in": 43199,
  "scope": "all"
}

此时 oauth2的授权码流程已经走完

再看密码模式

https://tools.ietf.org/html/rfc6749#page-24

在这里插入图片描述
在这里插入图片描述
其中 basic 的认证还是需要的

还需要服务提供商的用户和密码
但它不知道你的用户名和密码是怎么来得

发送请求报错Unsupported grant type: password

Unsupported grant type: password

解决
https://segmentfault.com/a/1190000012260914
MySecurityConfig中

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier("demoUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.httpBasic()   //指定身份认证的方式为表单登录
                .and()
                .authorizeRequests() //对请求授权
                .anyRequest()        //任何请求
                .authenticated()    //安全认证
        .and().userDetailsService(userDetailsService);
    }

    /**
     * 需要配置这个支持password模式
     * support password grant type
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

再次发送请求 成功

{
  "access_token": "6eb99d87-38da-45af-aca5-093628bc6fa0",
  "token_type": "bearer",
  "refresh_token": "829cdf29-06cf-45d4-82ae-789dde24b757",
  "expires_in": 43199,
  "scope": "all"
}

注意对于已经请求过token的用户在有效期内再次请求时 ,请求的token字符串是一样的

资源服务器的实现

在这里插入图片描述

@Configuration
@EnableResourceServer
public class WhaleResourceServerConfig {

}

此时我们这个服务器既是认证服务器又是资源服务器

启动访问 restlet client 工具访问 http://127.0.0.1:8080/hello
401错误
在这里插入图片描述

{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}

么有做身份认证

请求时需要把token带着

重新用密码授权模式获取token

请求头中加入要加入
“access_token": “09ed8d75-cfeb-4c84-939c-19bf8559e011”,
“token_type”:”bearer“
请求头如下
Authorization bearer 09ed8d75-cfeb-4c84-939c-19bf8559e011
注意token_type和access_token之间有一个空格
在这里插入图片描述

它就是通过这个access_token来确认身份

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值