一、场景
三个角色:用户(user),web应用(client),资源服务器和授权服务器合为服务器(server)
用户登录登录后可查看自己的信息
二、准备
2.1 数据库
schema
drop table if exists oauth2_client; drop table if exists oauth2_user; create table oauth2_user ( id bigint auto_increment, username varchar(100), password varchar(100), salt varchar(100), constraint pk_oauth2_user primary key(id) ) charset=utf8 ENGINE=InnoDB; create unique index idx_oauth2_user_username on oauth2_user(username); create table oauth2_client ( id bigint auto_increment, client_name varchar(100), client_id varchar(100), client_secret varchar(100), constraint pk_oauth2_client primary key(id) ) charset=utf8 ENGINE=InnoDB; create index idx_oauth2_client_client_id on oauth2_client(client_id);
data
DELIMITER ; delete from oauth2_user; delete from oauth2_client; insert into oauth2_user values(1,'admin','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f'); insert into oauth2_client values(1,'chapter17-client','c1ebe466-1cdc-4bd3-ab69-77c3561b9dee','d8346ea2-6017-43ed-ad68-19c0f971738b');
2.2 Server
zetark-oauth2-server
修改数据库链接 resources.properties
#dataSource configure connection.url=jdbc:mysql://mysql-server:3306/shiro connection.username=r00t connection.password=r00t
2.3 Client
zetark-oauth2-client
三、过程分析

1)2)用户访问client首页,检测到用户未登录,重定向到login

3)4)点击授权登录,输入admin/123456后点击登录并授权按钮


// 3)授权请求 http://localhost:8080/zetark-oauth2-server/oauth2login if (!isLogin && servletPath.startsWith("/login_authorize")) { String authorizeUrl = ClientParams.OAUTH_SERVER_AUTHORIZE_URL; authorizeUrl += "?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee"; authorizeUrl += "&response_type=code"; authorizeUrl += "&&redirect_uri=" + ClientParams.OAUTH_SERVER_REDIRECT_URI; response.sendRedirect(authorizeUrl); return; } // 4)授权响应 if (!isLogin && servletPath.startsWith("/login_response")) { String code = request.getParameter("code"); if (code != null) { // 6)7)令牌请求及响应 http://localhost:8080/zetark-oauth2-server/accessToken OAuthAccessTokenResponse tokenResponse = null; try { tokenResponse = OauthClient.makeTokenRequestWithAuthCode(code); } catch (OAuthProblemException e) { e.printStackTrace(); } catch (OAuthSystemException e) { e.printStackTrace(); } if (tokenResponse != null) { session.setAttribute("isLogin", true); session.setAttribute("token", tokenResponse.getAccessToken()); session.setMaxInactiveInterval(tokenResponse.getExpiresIn().intValue()); // 10)11) 根据token调用api String userInfoJson = OauthClient.getAuthedService(tokenResponse.getAccessToken()); Map<String, Object> userInfo = new Gson().fromJson(userInfoJson, Map.class); System.out.println(userInfo); session.setAttribute("user", userInfo); response.sendRedirect("index"); return; } } else { String errorDesc = request.getParameter("error_description"); System.out.println("登录失败:" + errorDesc); } }
访问过程

client_uri:/ client_uri:/login # 用户访问client首页/,由于未登录被重定向到/login页面 client_uri:/login_authorize server_uri:/oauth2login # 用户在/login页面点击授权登录后,向server发起授权请求,server返回登录页面/oauth2login server_uri:/authorize client_uri:/login_response # 用户在/oauth2login填写用户名密码后点击授权登录后,server验证后重定向到/login_resposne server_uri:/accessToken server_uri:/checkAccessToken # client在处理/login_response时接收code并再发起令牌请求,server返回令牌 server_uri:/v1/openapi/userInfo # client根据令牌信息请求api服务 client_uri:/index # 向用户返回/index页面
四、参考
https://github.com/ameizi/oltu-oauth2-example