博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security 之API 项目安全验证(基于basic-authentication)
阅读量:7139 次
发布时间:2019-06-28

本文共 4932 字,大约阅读时间需要 16 分钟。

===================================

Basic Authorization 规范
===================================
Request 头部:
Authorization: Basic QWxpY2U6MTIzNDU2
其中 QWxpY2U6MTIzNDU2 是user:pwd做 base64 编码, 格式是 user:pwd

response 头部:

WWW-Authenticate: Basic realm="My Realm"

按照 RFC 规范, 相同的 realm(域) 下的web page 将共享同样的 credentials, 所以推荐 realm 取值为 application name. realm 大小写敏感, 可以包含空格.

===================================
Rest API 示例
===================================
功能:
1. 演示如何启用 Basic Authorization
2. 如何使用 RestTemplate 访问受保护的 API接口

-----------------------------------

SecurityConfig 代码
-----------------------------------
关键点有:
0. 对于 /api/** 需要 ROLE_ADMIN 角色的账号访问, 对于 /guest/** 路径允许匿名访问.
1. 使用 HttpSecurity.httpBasic() 启用 Basic Authorization.
2. 使用 HttpSecurity.httpBasic().realmName() 设置 realm.
3. 使用 HttpSecurity.httpBasic().authenticationEntryPoint() 设置 BasicAuthenticationEntryPoint 对象, 如果一个请求通过验证, 该对象会自动为web response设定 WWW-Authenticate header, 如果未通过, 该对象会自动将HttpStatus设置为UNAUTHORIZED.
4. 显式启用了 STATELESS session 管理机制, 经测试,Spring Security 在Basic Authorization模式下, session自动就处于了 STATELESS 状态.
5. 对于 HttpMethod.OPTIONS 请求, 允许匿名访问. API 项目应该开放 OPTIONS 查询权限.

@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter {    //@formatter:off    @Override    public void configure(AuthenticationManagerBuilder builder) throws Exception {        builder.inMemoryAuthentication()                .withUser("123").password("123").roles("USER")                .and()                .withUser("ADMIN").password("ADMIN").roles("ADMIN");    }    //@formatter:on    private static String REALM = "MY SPRING SECURITY DEMO";    // @formatter:off    @Override    protected void configure(HttpSecurity http) throws Exception {        http           .authorizeRequests()               // 对于/api 路径下的访问需要有 ROLE_ADMIN 的权限              .antMatchers("/api/**").hasRole("ADMIN")               // 对于/guest 路径开放访问              .antMatchers("/guest/**").permitAll()               // 其他url路径之需要登陆即可.              .anyRequest().authenticated()              .and()           //启用 basic authentication          .httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthenticationEntryPoint())              .and()           //不创建 session          .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);    }    // @formatter:on    /**     * 生成 BasicAuthenticationEntryPoint 对象, 在该对象的支持下, 通过验证的请求, 返回的response 将会自动加上     * WWW-Authenticate Header.  在该对象的支持下, 未通过验证的请求, 返回的 response 为 UNAUTHORIZED 错误.     *     * @return     */    @Bean    public BasicAuthenticationEntryPoint getBasicAuthenticationEntryPoint() {        BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();        entryPoint.setRealmName(REALM);        return entryPoint;    }    /*     * 开放 Options 请求     */    @Override    public void configure(WebSecurity web) throws Exception {        // TODO Auto-generated method stub        web.ignoring()                .antMatchers(HttpMethod.OPTIONS, "/**");    }    @SuppressWarnings("deprecation")    @Bean    public NoOpPasswordEncoder passwordEncoder() {        BasicAuthenticationEntryPoint a;        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();    }}

-----------------------------------
受控 API Rest 类
-----------------------------------
对于 /api/** url需要 ROLE_ADMIN 角色的账号访问, 这里的代码很简单.

/* * 需要进行 Basic Auth 的API */@RestController@RequestMapping("/api")class ApiController {
@GetMapping("/books") public String getBooks() { return "API book"; }}

直接访问受控url, 弹出浏览器内置的登陆框, 见下图, 符合预期. 

 

-----------------------------------
RestTemplate 访问 Basic Authorization的API
-----------------------------------
关键点:
使用了 restTemplateBuilder.basicAuthorization(user,pwd).build() 来构建 RestTemplate, 这样的 RestTemplate 会自动在Request上加 Authorization Header.

 

/* * RestTemplate 访问 Basic Authorization的API的示例 */@RestController@RequestMapping("/guest")class DefaultController {    @GetMapping("/mybooks")    @ResponseBody    public String getMyBook() {        return "My Book";    }    private RestTemplate restTemplate;    @Autowired    private RestTemplateBuilder restTemplateBuilder;    @Autowired    void setRestTemplate(RestTemplateBuilder restTemplateBuilder) {         restTemplate = restTemplateBuilder.basicAuthorization("ADMIN", "ADMIN")         .build();    }    @GetMapping("/apibooks")    @ResponseBody    public String getApiBooks() {        return restTemplate.getForObject("http://localhost:8080/api/books", String.class);    }}

访问 http://localhost:8080/guest/apibooks 地址,  无需登陆即可得到 api 结果, 见下图, 符合预期. 

 

===================================

参考
===================================
http://websystique.com/spring-security/secure-spring-rest-api-using-basic-authentication/
http://www.bytestree.com/spring/restful-web-services-authentication-authorization/
https://www.baeldung.com/spring-security-basic-authentication

转载地址:http://bcvrl.baihongyu.com/

你可能感兴趣的文章
Vue.js笔记,从入门到精通
查看>>
Skype for Business实战演练之七:创建并发布新的拓扑
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
ADMT3.2域迁移之Server2003至Server2012系列(六)安装SQL Server2008
查看>>
webpack源码分析(1)----- webpack.cmd
查看>>
Oracle存在修改,不存在插入记录
查看>>
Java实现欢迎登录学员管理系统
查看>>
自我剖析,坚持有多难?
查看>>
find 指令
查看>>
系统学习redis之六——redis数据类型之set数据类型及操作
查看>>
【简报】帮助开发人员在线了解CSS Filter特性的工具 - CSS FilterLab
查看>>
软考信息系统监理师:2016年4月22日作业
查看>>
META-INF\MANIFEST.MF (系统找不到指定的路径)
查看>>
俄罗斯方块软件:C语言应用初步感受
查看>>
【安全牛学习笔记】收集敏感数据、隐藏痕迹
查看>>
LinkedME|Deep Linking技术你真的了解吗
查看>>
Memcached,redis监控详解
查看>>
Linux-13软件安装
查看>>
MySQL 基本语句
查看>>