OAuth 2 实现简单登录授权

1.OAuth2.0 进阶

根据官方标准,OAuth 2.0 共用四种授权模式:

  • Authorization Code: 用在服务端应用之间,这种最复杂,也是本文采用的模式;
  • Implicit: 用在移动app或者webapp(这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)
  • Resource Owner Password Credentials(password): 应用直接都是受信任的(都是由一家公司开发的,本例子使用)
  • Client Credentials: 用在应用API访问。

在这里插入图片描述

2. 基于 SpringBoot 实现认证/授权

1.搭建授权服务器
(1) pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

(2) application.properties

server.port=8110 ## 监听端口

(3) AuthorizationServerApplication.java

@EnableResourceServer // 启用资源服务器
public class AuthorizationServerApplication {
    // ...
}

(4) 配置授权服务的参数

@Configuration
@EnableAuthorizationServer
public class Oauth2AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("webapp").secret("secret") //客户端 id/secret
                .authorizedGrantTypes("authorization code") //授权妈模式
                .scopes("user_info") //权限范围,可随意设置,用到的时候和此处保持一致即可
                .autoApprove(true) //自动审批
                .accessTokenValiditySeconds(3600); //有效期1hour
    }
}

@Configuration
public class Oauth2WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                .antMatchers("/login", "/oauth/authorize/oauth/logout")
                .and().authorizeRequests().anyRequest().authenticated()
                .and().formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN");
    }
}

2.客户端访问(业务网站)
(1) pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

(2) application.properties

server port=8080
security.oauth2.client.client-id=webapp
security.oauth2.client.client-secret=secret
security.oauth2.client.access-token-uri=http://localhost:8110/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8110/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:8110/oauth/user

(3) 配置 WEB 安全

@Configuration
@EnableOAuth2Sso
public class Oauth2WebsecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests()
                .antMatchers("/", "/login").permitAll()
                .anyRequest().authenticated();
    }
}

@RestController
public class Oauth2ClientController {
    @GetMapping("/")
    public ModelAndView index() {
        return new ModelAndView("index");
    }

    @GetMapping("/welcome")
    public ModelAndView welcome() {
        return new ModelAndView("welcome");
    }
}

3. 用户权限控制(基于角色)

  • 授权服务器中,定义各用户拥有的角色: user=USER, admin=ADMIN/USER, root=ROOT/ADMIN/USER
  • 业务网站中(client),注解标明哪些角色可
@RestController
public class Oauth2ClientController {
    @GetMapping("/welcome")
    public ModelAndView welcome() {
        return new ModelAndView("welcome");
    }

    @GetMapping("/api/user")
    @PreAuthorize("hasAuthority('USER')")
    public Map<String, Object> apiUser() {
    }

    @GetMapping("/api/admin")
    @PreAuthorize("hasAuthority('ADMIN')")
    public Map<String, Object> apiAdmin() {
    }

    @GetMapping("/api/root")
    @PreAuthorize("hasAuthority('ROOT')")
    public Map<String, Object> apiRoot() {
    }
}

4.权限控制方案(普通结构)
在这里插入图片描述
微服务应用与常规服务架构不同,在微服务架构中,Authorization Server/Resource Server 是作为微服务存在的,用户的登录可以通过API网关一次性完成,无需与无法跳转至内网的 Authorization Server 来完成。
在这里插入图片描述
解析:实际就是用户首次访问会去授权服务器进行认证,认证后返回用户的身份信息和权限角色信息,用户输入账号密码,进行身份验证通过后,当访问资源,进行权限验证,通过的话则可以访问指定的接口数据。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OAuth2 是一个授权框架,可以用于实现单点登录。下面是一个使用 OAuth2 实现单点登录的示例代码: 1. 创建一个 OAuth2 服务器 ```python from flask import Flask from flask_oauthlib.provider import OAuth2Provider app = Flask(__name__) oauth = OAuth2Provider(app) # 定义客户端和用户数据 clients = { 'client_id': 'client_secret' } users = { 'user_id': 'password' } # 定义授权请求 @oauth.clientgetter def get_client(client_id): return clients.get(client_id) # 定义用户密码验证 @oauth.usergetter def get_user(username, password, *args, **kwargs): if users.get(username) == password: return {'id': username} # 定义授权逻辑 @oauth.authorize_handler def authorize(client_id, response_type, redirect_uri, *args, **kwargs): # 判断用户是否已经登录 user = kwargs.get('user') if user: return True else: # 重定向到登录页面 return redirect('/login') # 定义令牌生成逻辑 @oauth.tokengetter def get_token(access_token=None, refresh_token=None): # 返回访问令牌和刷新令牌 return access_token, refresh_token if __name__ == '__main__': app.run() ``` 2. 创建一个客户端应用 ```python from flask import Flask, request from flask_oauthlib.client import OAuth2Client app = Flask(__name__) oauth = OAuth2Client(app) # 定义授权逻辑 @app.route('/login') def login(): # 获取授权码 redirect_uri = request.host_url + 'callback' return oauth.authorize_redirect(redirect_uri=redirect_uri) # 定义回调逻辑 @app.route('/callback') def callback(): # 获取访问令牌和刷新令牌 redirect_uri = request.host_url + 'callback' return oauth.authorized_response(redirect_uri=redirect_uri) if __name__ == '__main__': app.run() ``` 3. 创建一个受保护的资源 ```python from flask import Flask from flask_oauthlib.provider import OAuth2Provider app = Flask(__name__) oauth = OAuth2Provider(app) # 定义客户端和用户数据 clients = { 'client_id': 'client_secret' } users = { 'user_id': 'password' } # 定义授权请求 @oauth.clientgetter def get_client(client_id): return clients.get(client_id) # 定义用户密码验证 @oauth.usergetter def get_user(username, password, *args, **kwargs): if users.get(username) == password: return {'id': username} # 定义授权逻辑 @oauth.authorize_handler def authorize(client_id, response_type, redirect_uri, *args, **kwargs): # 判断用户是否已经登录 user = kwargs.get('user') if user: return True else: # 重定向到登录页面 return redirect('/login') # 定义令牌生成逻辑 @oauth.tokengetter def get_token(access_token=None, refresh_token=None): # 返回访问令牌和刷新令牌 return access_token, refresh_token # 定义受保护的资源 @app.route('/protected') @oauth.require_oauth('email') def protected(): # 获取用户信息 user = request.oauth.user return 'Hello, {}!'.format(user['email']) if __name__ == '__main__': app.run() ``` 以上是一个简单OAuth2 单点登录示例代码,仅供参考。实际应用中需要根据具体需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bst@微胖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值