使用Spring MVC测试Spring Security Oauth2 API
不是因为看到希望了才去坚持,而坚持了才知道没有希望。

前言
在Spring Security源码分析十一:Spring Security OAuth2整合JWT和Spring Boot 2.0 整合 Spring Security Oauth2中,我们都是使用Restlet Client - REST API Testing测试被Oauth2保护的API。在本章中,我们将展示如何使用MockMvc测试Oauth2的API。
修改pom.xml
添加spring-security-test依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
修改MerryyouResourceServerConfig配置
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.formLogin()
.successHandler(appLoginInSuccessHandler)//登录成功处理器
.and()
.authorizeRequests()
.antMatchers("/user").hasRole("USER")
.antMatchers("/forbidden").hasRole("ADMIN")
.anyRequest().authenticated().and()
.csrf().disable();
// @formatter:ON
}
- 修改
MerryyouResourceServerConfig配置,增加对指定路径的角色校验。 - 默认角色为
ROLE_USER,详见MyUserDetailsService
@Component
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User(username, "123456", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
}
}
- 关于为何是
hasRole("USER")而不是hasRole("ROLE_USER")请参考:Spring Security源码分析十三:Spring Security 基于表达式的权限控制 @formatter:off和@formatter:ON此段代码不进行格式化
增加/user和/forbidden请求映射
@GetMapping("/user")
public Object getCurrentUser1(Authentication authentication, HttpServletRequest request) throws UnsupportedEncodingException {
log.info("【SecurityOauth2Application】 getCurrentUser1 authenticaiton={}", JsonUtil.toJson(authentication));
String header = request.getHeader("Authorization");
String token = StringUtils.substringAfter(header, "bearer ");
Claims claims = Jwts.parser().setSigningKey(oAuth2Properties.getJwtSigningKey().getBytes("UTF-8")).parseClaimsJws(token).getBody();
String blog = (String) claims.get("blog");
log.info("【SecurityOauth2Application】 getCurrentUser1 blog={}", blog);
return authentication;
}
@GetMapping("/forbidden")
public String getForbidden() {
return "forbidden";
}
/user请求需要USER角色/forbidden请求需要ADMIN角色
增加测试类SecurityOauth2Test
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = SecurityOauth2Application.class)
@Slf4j
public class Oauth2MvcTest {
@Autowired
private WebApplicationContext wac;
@Autowired
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
//clientId
final static String CLIENT_ID = "merryyou";
//clientSecret
final static String CLIENT_SECRET = "merryyou";
//用户名
final static String USERNAME = "admin";
//密码
final static String PASSWORD = "123456";
private static final String CONTENT_TYPE = "application/json;charset=UTF-8";
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(springSecurityFilterChain).build();//初始化MockMvc对象,添加Security过滤器链
}
- 初始化
Oauth2信息
obtainAccessToken
public String obtainAccessToken() throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "password");
params.add("client_id", CLIENT_ID);
params.add("username", USERNAME);
params.add("password", PASSWORD);
// @formatter:off
ResultActions result = mockMvc.perform(post("/oauth/token")
.params(params)
.with(httpBasic(CLIENT_ID, CLIENT_SECRET))
.accept(CONTENT_TYPE))
.andExpect(status().isOk())
.andExpect(content().contentType(CONTENT_TYPE));
// @formatter:on
String resultString = result.andReturn().getResponse().getContentAsString();
JacksonJsonParser jsonParser = new JacksonJsonParser();
// System.out.println(jsonParser.parseMap(resultString).get("access_token").toString());
return jsonParser.parseMap(resultString).get("access_token").toString();
}
测试obtainAccessToken
@Test
public void getAccessToken() throws Exception {
final String accessToken = obtainAccessToken();
log.info("access_token={}", accessToken);
}
控制台打印:
access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE1MjY0NjEwMzgsImJsb2ciOiJodHRwczovL2xvbmdmZWl6aGVuZy5naXRodWIuaW8vIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6ImE1MmE2NDI4LTcwNzctNDcwZC05M2MwLTc0ZWNlNjFhYTlkMCIsImNsaWVudF9pZCI6Im1lcnJ5eW91In0.CPmkZmfOkgDII29RMIoMO7ufAe5WFrQDB7SaMDKa128
UnauthorizedTest
/**
* 未授权 401
*
* @throws Exception
*/
@Test
public void UnauthorizedTest() throws Exception {
// mockMvc.perform(get("/user")).andExpect(status().isUnauthorized());
ResultActions actions = mockMvc.perform(get("/user"));
int status = actions.andReturn().getResponse().getStatus();
Assert.assertTrue(status == HttpStatus.UNAUTHORIZED.value());
}
- 未授权
401
forbiddenTest
/**
* 禁止访问 403
*
* @throws Exception
*/
@Test
public void forbiddenTest() throws Exception {
final String accessToken = obtainAccessToken();
log.info("access_token={}", accessToken);
mockMvc.perform(get("/forbidden").header("Authorization", "bearer " + accessToken)).andExpect(status().isForbidden());
}
- 禁止访问
403
accessTokenOk
/**
* 允许访问 200
*
* @throws Exception
*/
@Test
public void accessTokenOk() throws Exception {
final String accessToken = obtainAccessToken();
log.info("access_token={}", accessToken);
mockMvc.perform(get("/user").header("Authorization", "bearer " + accessToken)).andExpect(status().isOk());
}
- 允许访问
200
代码下载
- github:https://github.com/longfeizheng/security-oauth2
- gitee:https://gitee.com/merryyou/security-oauth2
推荐文章
- Java创建区块链系列
- Spring Security源码分析系列
- Spring Data Jpa 系列
- 【译】数据结构中关于树的一切(java版)
- SpringBoot+Docker+Git+Jenkins实现简易的持续集成和持续部署

使用Spring MVC测试Spring Security Oauth2 API的更多相关文章
- Spring MVC测试框架
原文链接:http://jinnianshilongnian.iteye.com/blog/2004660 Spring MVC测试框架详解——服务端测试 博客分类: springmvc杂谈 spri ...
- Spring MVC测试框架详解——服务端测试
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...
- Spring MVC和Spring Boot的理解以及比较
Spring MVC是什么?(1)Spring MVC是Spring提供的一个强大而灵活的模块式web框架.通过Dispatcher Servlet, ModelAndView 和 View Reso ...
- Spring MVC 到 Spring Boot 的简化之路(山东数漫江湖)
背景 从Servlet技术到Spring和Spring MVC,开发Web应用变得越来越简捷.但是Spring和Spring MVC的众多配置有时却让人望而却步,相信有过Spring MVC开发经验的 ...
- 【转】Spring,Spring MVC及Spring Boot区别
对于一个Java开发者来说,Spring可谓如雷贯耳,无论是Spring框架,还是Spring引领的IOC,AOP风格,都对后续Java开发产生的深远的影响,同时,Spring社区总能及时响应开发者的 ...
- Spring MVC 到 Spring BOOT 的简化之路
背景 Spring vs Spring MVC vs Spring Boot Spring FrameWork Spring 还能解决什么问题 Spring MVC 为什么需要Spring Boot ...
- Spring MVC 和 Spring 总结
1. 为什么使用Spring ? 1). 方便解耦,简化开发 通过Spring提供的IoC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合. 2). AOP编程的 ...
- Spring,Spring MVC及Spring Boot区别
什么是Spring?它解决了什么问题? 我们说到Spring,一般指代的是Spring Framework,它是一个开源的应用程序框架,提供了一个简易的开发方式,通过这种开发方式,将避免那些可能致使代 ...
- spring、spring mvc与spring boot的区别是什么?
Spring 的功能 Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等.但他们的基础都是Spring 的 ioc和 aop ioc 提供了依赖注入的容器 ao ...
随机推荐
- WINCE之“系统事件”——System/Events
1. 简介 Event--事件,相信有线程概念的编程人员都知道,它可以用来同步不同进程.不同线程的通信.在Windows CE 5.0系统中,有一种我称之为"系统事件"的Event ...
- 【Android 应用开发】Activity生命周期 与 Activity 之间的通信
一. Activity生命周期 上图 1. Activity状态 激活状态 : Activity出于前台 , 栈顶位置; 暂停状态 : 失去了焦点 , 但是用户仍然可以看到 , 比如弹出一个对话框 , ...
- SharePoint 2007 列表页定制--4个默认页定制
以"简单的领导简介"为例,欢迎大家指正 背景:项目中需要有领导简介的模块,就开始制作领导简介,本来很简单,有一个列表就可以,然后在前台展示出来,但是客户看到我们的效果,尤其输入领导 ...
- objective-c中线程编程一例
/* print with threads : print every file's first n char contents under the path that pass to this pr ...
- combination sum、permutation、subset(组合和、全排列、子集)
combination sum I.permutation I.subsets I 是组合和.全排列.子集的第一种情况,给定数组中没有重复的元素. combination sum II.permut ...
- 初识Java——循环语句
循环语句就是在一定条件下反复执行某一个操作.具体有三种方法实现: 1while循环语句 while语句也称作条件判断语句,它的循环方式为利用一个条件来控制是否要反复执行.语法如下: while(条件语 ...
- 任务调度利器:Celery
http://www.liaoxuefeng.com/article/00137760323922531a8582c08814fb09e9930cede45e3cc000 Celery是Python开 ...
- Windows下对拍
What is 对拍 Tool: 你的程序 可以输出正解的暴力程序 数据生成器 输出对比器 RP 用来干什么? 用来造数据,检验你的程序的正确性,以方便修改和出现未考虑到的情况 如何工作? 数据生成器 ...
- kaggle入门项目:Titanic存亡预测(三)数据可视化与统计分析
---恢复内容开始--- 原kaggle比赛地址:https://www.kaggle.com/c/titanic 原kernel地址:A Data Science Framework: To Ach ...
- 第二课:Hadoop集群环境配置
一.Yum配置 1.检查Yum是否安装 rpm -qa|grep yum 2.修改yum源,我使用的是163的镜像源(http://mirrors.163.com/),根据自己的系统选择源, #进入目 ...