1.前言
oauth2 是现在比较流行的授权机制,它可以不用让用户输入用户和密码通过别的网站的授权直接登录应用.
spring 全家桶也提供了关于oauth2的解决方案: oauth2-client 和 oauth2-resource-server. server是服务端的用来验证token,我们这里使用client,用来获取token,服务端是国内的gitee.
2.实现
使用springboot引入依赖
implementation 'org.webjars:jquery:3.4.1'
implementation 'org.webjars:js-cookie:2.1.0'
implementation 'org.webjars:bootstrap:4.3.1'
implementation 'org.webjars:webjars-locator-core'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
在application.yml文件里面输入gitee的client-id和client-secret
这个在gitee的用户管理里面新建
spring: security: user: password: password oauth2: client: registration: github: client-id: 8800a24423a23376 client-secret: 41aed2a18cb0094b0b1edf22e2 gitee: client-id: e402cf266b38b5666992dfe99c94002a0b6b08186e client-secret: 4d0872ea166be4aa7f843ddb479e68d3764ff authorization-grant-type: authorization_code redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}' client-name: gitee provider: gitee scope: - user_info
authorization-grant-typ 一般是authorization_code,这个要看每个授权服务器的文档的要求.
redirect-uri要和gitee上设置的回调地址一样{baseUrl}就是应用的原始地址.{registrationId}就是gitee.
scope加上user_info,这样我们就可以获取用户信息
因为oauth-client官方只提供了github和google的登录,所以其他方式需要自己定义provider
spring:
security:
user:
password: password
oauth2:
client:
provider:
gitee:
authorization-uri: https://gitee.com/oauth/authorize
token-uri: https://gitee.com/oauth/token
user-info-uri: https://gitee.com/api/v5/user
user-name-attribute: name
authorization-uri 是gitee进行授权的地址,token-uri是用来获取access_token的地址,user-info-uri用来获取用户信息,user-name-attribute获取用户名
定义好后添加spring security 的配置
@SpringBootApplication
@RestController
public class OauthTest3Application extends WebSecurityConfigurerAdapter {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return Collections.singletonMap("name", principal.getAttribute("name"));
}
public static void main(String[] args) {
SpringApplication.run(OauthTest3Application.class, args);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(a -> a
.antMatchers("/", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login();
http.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
.csrf().disable();
// @formatter:on
}
}
注意有个oauth2Login和controller
最后自己做一个登录页面放到resources的static文件夹下
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>Demo</title> <meta name="description" content="" /> <meta name="viewport" content="width=device-width" /> <base href="/" /> <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css" /> <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script> <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script> <script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script> </head> <body> <h1>Demo</h1> <div class="container"> <div class="container unauthenticated"> With GitHub: <a href="/oauth2/authorization/gitee">click here</a> </div> <div class="container authenticated" style="display: none"> Logged in as: <span id="user"></span> </div> <div class="container authenticated"> Logged in as: <span id="user"></span> <div> <button onClick="logout()" class="btn btn-primary">Logout</button> </div> </div> <div id="login_container"></div> </div> <script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script> <script type="text/javascript"> $.ajaxSetup({ beforeSend : function(xhr, settings) { if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') { if (!(/^http:.*/.test(settings.url) || /^https:.*/ .test(settings.url))) { // Only send the token to relative URLs i.e. locally. xhr.setRequestHeader("X-XSRF-TOKEN", Cookies .get('XSRF-TOKEN')); } } } }); $.get("/user", function(data) { $("#user").html(data.name); $(".unauthenticated").hide() $(".authenticated").show() }); var logout = function() { $.post("/logout", function() { $("#user").html(''); $(".unauthenticated").show(); $(".authenticated").hide(); }) return true; } </script> </body> </html>
3.验证
和我gitee账户定义的一个名称没有问题
目前还不知道access_token是怎么获取的,官网文档还不完善,有大佬知道的话可以留言指导我一下,不胜感激.
从这点来说,spring security 比 shiro 强了一点,支持 oauth 2,配合 spring boot 非常简便.
因为使用的是框架,整个流程简化了许多,不排除spring boot security 框架以后会发生变化,鼓励参考官方文档.