不是因为看到希望了才去坚持,而坚持了才知道没有希望。
前言
在和中,我们都是使用测试被Oauth2
保护的API
。在本章中,我们将展示如何使用MockMvc
测试Oauth2
的API
。
修改pom.xml
添加spring-security-test
依赖
复制代码 org.springframework.security spring-security-test
修改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
@Componentpublic 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")
请参考: @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)@Slf4jpublic 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 MultiValueMapparams = 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:
- gitee:
推荐文章
???关注微信小程序java架构师历程 上下班的路上无聊吗?还在看小说、新闻吗?不知道怎样提高自己的技术吗?来吧这里有你需要的java架构文章,1.5w+的java工程师都在看,你还在等什么?