代码拉取完成,页面将自动刷新
获取CLIENT_ID和CLIENT_SECRET:
static final String CLIENT_ID = "0a0e670f4ac34bf8c77711a61e13520a151e5188511350f211829bcb578756fc";
static final String CLIENT_SECRET = "980a02c97074b79f157bae9193cd01f1cf89ff689425cc993da4120240612fb5";
(2)编写重定向过滤器的业务逻辑: 当用户访问/oauth2/gitee时,本重定向过滤器拦截请求,并将用户重定向到码云三方认证页面上
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 如果不是/oauth2/gitee请求,则继续下一个过滤器。
if (!request.getRequestURI().endsWith(DEFAULT_AUTHORIZATION_REQUEST_BASE_URI)) {
filterChain.doFilter(request, response);
return;// 执行完安全过滤器链后不执行后面的代码。
}
/// 步骤二:编写重定向过滤器的业务逻辑。
String redirectUrl = UriComponentsBuilder.fromUriString("https://gitee.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code")
.encode()
.buildAndExpand(CLIENT_ID,REDIRECT_URI)
.toUriString();
redirectUrl = response.encodeRedirectURL(redirectUrl);
response.sendRedirect(redirectUrl);
}
(3)使用码云access_token API向码云认证服务器发送post请求获取access_token:
private String getAccessToken(String code) {
/// 步骤三:使用码云access_token API向码云认证服务器发送post请求获取access_token。
URI accessUrl = UriComponentsBuilder.fromHttpUrl(ACCESS_TOKEN_API_URI)
.encode()
.buildAndExpand(code,CLIENT_ID,REDIRECT_URI,CLIENT_SECRET)
.toUri();
RequestEntity<Void> requestEntity = RequestEntity
.post(accessUrl)
.header("User-agent","Chrome")
.build();
String result = rest.exchange(requestEntity,String.class).getBody();
Map<String,Object> stringObjectMap = new JacksonJsonParser().parseMap(result);
return (String)stringObjectMap.get("access_token");
}
(4)使用码云API获取授权用户的资料:
private Map<String, Object> getUserInfo(String accessToken) {
/// 步骤四:使用码云API获取授权用户的资料。
URI userUrl=UriComponentsBuilder.fromHttpUrl(USER_INFO_URI)
.encode()
.buildAndExpand(accessToken)
.toUri();
RequestEntity<Void> requestEntity = RequestEntity
.get(userUrl)
.header("User-agent","Chrome")
.build();
String result=rest.exchange(requestEntity,String.class).getBody();
JacksonJsonParser jacksonJsonParser=new JacksonJsonParser();
return jacksonJsonParser.parseMap(result);
}
(5)把自定义的两个Filter加进安全过滤链:
public void configure(H http) {
/// 步骤五:把自定义的两个Filter加进安全过滤链
http.addFilterAfter(new GiteeOAuth2RedirectFilter(), SecurityContextPersistenceFilter.class);
http.addFilterAfter(new GiteeOAuth2LoginAuthenticationFilter(), SecurityContextPersistenceFilter.class);
}
(6)把我们自定义的SecurityConfigurer应用到安全过滤链:
protected void configure(HttpSecurity http) throws Exception {
// 不指定path,本安全过滤链会匹配所有请求。
http
.authorizeRequests()
.antMatchers("/").permitAll()// 首页放行
.anyRequest().hasAnyAuthority("USER").and()
.formLogin()
.loginPage("/user/login_frontend").permitAll()
.defaultSuccessUrl("/user").and()
.logout()
.logoutUrl("/user/logout").permitAll()
.logoutSuccessUrl("/user/login_frontend?logout").and()
// 自定义访问拒绝异常处理逻辑
.exceptionHandling().accessDeniedHandler(UserSecurityConfig::accessDeniedHandle)
/// 步骤六:把我们自定义的SecurityConfigurer应用到安全过滤链
.and()
.apply(giteeOAuth2LoginConfigurer);
}
(7)改造/user接口,返回码云用户资料给前端;改造user.ftlh模板用于显示用户资料:
@GetMapping("/user")
public String userIndex(Model model) {
/// 步骤七:改造/user接口,返回码云用户资料给前端;改造user.ftlh模板用于显示用户资料。
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userDetail = (UserDetails) authentication.getPrincipal();
model.addAttribute("userDetails",userDetail);
return "user";
}
(8)编写单元测试。模拟一个登录用户,访问受保护的接口/test,断言接口的返回内容body部分是否一致:
@Test
@WithMockUser(username = "user",authorities = {"USER"})
public void test() throws Exception {
/// 步骤八:模拟一个登录用户,访问受保护的接口/test,断言接口的返回内容body部分是否一致。
mvc.perform(get("/test").header("User-Agent","Chrome"))
.andExpect(status().isOk())
.andExpect(content().string("欢迎您"));
}
通过此次实验,我了解如何使用Spring Security框架、配置Spring Security的安全过滤链、编写Spring Security单元测试、创建接入码云的应用、码云OAuth2认证基本流程、使用码云API、了解使用模板引擎或前端框架制作用户登录界面,初步了解这些知识,以后的学习中不断深入学习和掌握。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。