文档章节

使用Spring MVC测试Spring Security Oauth2 API

郑龙飞
 郑龙飞
发布于 05/16 15:21
字数 799
阅读 276
收藏 12

不是因为看到希望了才去坚持,而坚持了才知道没有希望。

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/spring-security-OAuth206.png

前言

Spring Security源码分析十一:Spring Security OAuth2整合JWTSpring Boot 2.0 整合 Spring Security Oauth2中,我们都是使用Restlet Client - REST API Testing测试被Oauth2保护的API。在本章中,我们将展示如何使用MockMvc测试Oauth2API

修改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"));
    }
}

增加/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

代码下载

推荐文章

  1. Java创建区块链系列
  2. Spring Security源码分析系列
  3. Spring Data Jpa 系列
  4. 【译】数据结构中关于树的一切(java版)
  5. SpringBoot+Docker+Git+Jenkins实现简易的持续集成和持续部署

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/wechat/xiaochengxu.png

🙂🙂🙂关注微信小程序java架构师历程 上下班的路上无聊吗?还在看小说、新闻吗?不知道怎样提高自己的技术吗?来吧这里有你需要的java架构文章,1.5w+的java工程师都在看,你还在等什么?

© 著作权归作者所有

共有 人打赏支持
郑龙飞

郑龙飞

粉丝 48
博文 48
码字总数 60737
作品 0
邯郸
程序员
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致dad
08/03
0
0
Secures your applications with Spring Security 5 and Keycloak

Spring Security 5 brought new OAuth2/OIDC client instead of the legacy client support in the old Spring Security OAuth sub project. The new OAuth2 umbrella modules in the core p......

hantsy
04/24
0
0
Spring Cloud 安全:集成OAuth2实现身份认证和单点登录

1、概述 Spring Cloud 的安全模块可以为Spring Boot应用提供基于令牌的安全特性。具体讲就是支持OAuth2协议来实现单点登录(SSO),可以很方便地在资源服务之间传递身份令牌,以及使用嵌入式...

RaiseHead
07/20
0
0
Spring Security OAuth2 SSO

通常公司肯定不止一个系统,每个系统都需要进行认证和权限控制,不可能每个每个系统都自己去写,这个时候需要把登录单独提出来 登录和授权是统一的 业务系统该怎么写还怎么写 最近学习了一下...

不要乱摸
07/11
0
0
Spring-Security-OAuth2

OAuth 是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而不需要将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌,...

李玉长
05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
48分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
23
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
1K
17
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部