因为 Basic Auth 的身份信息是写在请求中,被截获账号密码可能会泄露,为此增加一重ip认证

在实际应用中,可能会用spring boot  写一些微服务去做底层的一些预处理,然后再开放一些接口传输数据。为了安全,同城要做一些访问的认证,也不用选太复杂的认证方式,就用 Basic Auth就可以,再在此基础上再做一些认证,比如这里的ip。

为此,需要两个方面的思考

1、如何做 Basic Auth 的认证
2、如何检验访问者的ip并授权

下面通过代码说明

一、依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

二、控制器Controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;/*** api*/
@RestController
@RequestMapping("/translate")
public class TranslateController {@ResponseBody@RequestMapping(value = "/AuthTest", method = RequestMethod.GET)public String AuthTest() {Authentication auth = SecurityContextHolder.getContext().getAuthentication();System.out.println(auth.getName());return "OK";}}

三、匿名用户访问无权限资源时的异常处理 类

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 匿名用户访问无权限资源时的异常处理* 重写commence,处理异常* 当 认证失败时 会跳转到  commence 方法,所以这里可以做一些定制化*/
@Component
public class Authenication extends BasicAuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) throws IOException {response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName());response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);PrintWriter writer = response.getWriter();writer.println("账号密码不正确 HTTP Status 401 - " + authEx.getMessage());}@Overridepublic void afterPropertiesSet() {setRealmName("translate");super.afterPropertiesSet();}
}

四、web 安全认证配置 类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {@Value("${myname}")private String myname;@Value("${mypassword}")private String mypassword;private final static Logger log = LoggerFactory.getLogger(WebSecurityConfig.class);@Autowiredprivate AuthenticationEntryPoint authEntryPoint;@Overrideprotected void configure(HttpSecurity http) throws Exception {// 关闭跨域保护http.cors().and().csrf().disable();// 所有的请求都要验证http.authorizeRequests().anyRequest().authenticated();// 使用authenticationEntryPoint验证 user/passwordhttp.httpBasic().authenticationEntryPoint(authEntryPoint);}@Beanpublic BCryptPasswordEncoder passwordEncoder() {BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();return bCryptPasswordEncoder;}/*** 配置授权的 账号密码* 这里是在配置文件配置好** @param auth* @throws Exception*/@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {log.info("user: " + myname);log.info("password: " + mypassword);String encrytedPassword = this.passwordEncoder().encode(mypassword);System.out.println("Encoded password = " + encrytedPassword);// 这里使用写死的验证InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> mngConfig = auth.inMemoryAuthentication();UserDetails u1 = User.withUsername(myname).password(encrytedPassword).roles("ADMIN").build();mngConfig.withUser(u1);}@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*").allowedHeaders("*");}
}

五、配置文件  application.yml

server:port: 9999servlet:context-path: /translate-web/#请求账号密码
myname: test
mypassword: 123456#授权ips,逗号隔开
ipAuthSwitch: true
ips: 192.168.1.2,0:0:0:0:0:0:0:1

六、postman 访问(带上认证信息)

至此,整个Basic Auth认证就完成了

下面我们在上面的基础上补充ip认证

原理就是用拦截器拦截请求,然后在请求中获取ip,将这个ip和配置授权的ip做对比,符合就通过,否则不允许请求

七、自定义拦截器

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Set;/*** 拦截器*/
public class TranslateInterceptor implements HandlerInterceptor {private final static Logger log = LoggerFactory.getLogger(TranslateInterceptor.class);long start = System.currentTimeMillis();private Set<String> ips;private Boolean ipAuthSwitch;public TranslateInterceptor( Set<String> ips, Boolean ipAuthSwitch) {this.ips = ips;this.ipAuthSwitch = ipAuthSwitch;}/*** preHandle是在请求执行前执行的** @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {start = System.currentTimeMillis();String ip = request.getRemoteAddr();log.info("request ip: " + ip);/*** 返回true,postHandler和afterCompletion方法才能执行* 否则false为拒绝执行,起到拦截器控制作用*/if (ipAuthSwitch) {if(StringUtils.isNotEmpty(ip) && ips.contains(ip)){return true;}else{log.info("ip:{} No authority", ip);return false;}}else{return true;}}/*** postHandler是在请求结束之后,视图渲染之前执行的,但只有preHandle方法返回true的时候才会执行** @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {System.out.println("Interception cost=" + (System.currentTimeMillis() - start));}/*** afterCompletion是视图渲染完成之后才执行,同样需要preHandle返回true** @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {//该方法通常用于清理资源等工作}}

八、拦截器配置

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;/*** 拦截器配置*/
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {@Value("${ips}")private String ips;@Value("${ipAuthSwitch}")private Boolean ipAuthSwitch;@Overridepublic void addInterceptors(InterceptorRegistry registry) {String[] split = ips.split(",");Set<String> ipSet = new HashSet<>(Arrays.asList(split));registry.addInterceptor(new TranslateInterceptor(ipSet, ipAuthSwitch))//添加需要验证登录用户操作权限的请求.addPathPatterns("/**")//这里add为“/**”,下面的exclude才起作用,且不管controller层是否有匹配客户端请求,拦截器都起作用拦截//排除不需要验证登录用户操作权限的请求.excludePathPatterns("/wang").excludePathPatterns("/css/**").excludePathPatterns("/js/**").excludePathPatterns("/images/**");//这里可以用registry.addInterceptor添加多个拦截器实例,后面加上匹配模式super.addInterceptors(registry);//最后将register往这里塞进去就可以了}
}

最后感谢两位博主的资料

springboot成神之——Basic Auth应用:springboot成神之——Basic Auth应用 - qz奔跑的马 - 博客园

Spring Boot之拦截器与过滤器(完整版) :Spring Boot之拦截器与过滤器(完整版) - 一飞要上天 - 博客园

springboot Basic Auth 暴露API 访问认证相关推荐

  1. SpringBoot微信公众号授权访问认证文件部署

    一.将微信给的信息新建认证文件存放到static目录 二.修改静态资源映射 三.有授权功能的设置为不需要授权

  2. java basic类似的地方_java – Shiro使用HTTP Basic Auth或匿名访问相同的URI

    您可以滚动自己的自定义shiro过滤器.扩展类BasicHttpAuthenticationFilter并覆盖onPreHandle,您可以在其中检查servlet请求方法(如果它是GET或POST) ...

  3. Rest Api 项目添加 Basic Auth 认证

    title: Rest Api 项目添加 Basic Auth 认证 date: 2022-10-10 22:09 tags: [Java,Spring Boot,Rest Api,Basic Aut ...

  4. Nginx配置Basic Auth登录认证的实现方法

    这篇文章主要介绍了Nginx配置Basic Auth登录认证的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 有时候我们通过nginx搭建了一台文件服务器, 一般 ...

  5. 用 PHP 进行 HTTP 认证,Basic Auth

    实现基本的简单Basic Auth认证. php手册 可以用 header() 函数来向客户端浏览器发送"Authentication Required"信息,使其弹出一个用户名/ ...

  6. java鉴权_一个开箱即用的高效认证鉴权框架,专注于restful api的认证鉴权动态保护...

    作者:tomsun28 来源:SegmentFault 思否 写在开头 看了看这个专栏的最近一篇文章已经是两年前了,时间过得好快.应该是出学校后时间就很快了.两年前因为用shiro后,自己就按着想法开 ...

  7. RESTful Api 身份认证总结

    RESTful API是基于HTTP协议的API(Application Programming Interface),它的核心是将所有的API都理解为一个网络资源,客户端请求资源时操作的是资源的表述 ...

  8. Basic Auth 和 OAuth的区别

    开放平台有两种认证方式,一种是Basic Auth,一种是OAuth. 关于OAuth1,OAuth2的异同  移步->> https://blog.csdn.net/qq_1502829 ...

  9. laravel auth.php,Laravel 用户认证 Auth

    很多应用是需要登陆后才能操作,Laravel提供了一个auth工具来实现用户的认证功能.并且有一个config/auth.php来配置auth工具.大概看一下auth工具的常用方法 Auth::che ...

  10. php lumen auth,学习 Lumen 用户认证 (一)

    好久没写 PHP 代码了,尤其是 Lumen,我是 Lumen 的忠实用户,自从面世开始,我就将 Lumen 作为我 API 的主要框架使用. 但说到 API,不得不说的一个概念:「前后端分离」,现在 ...

最新文章

  1. linux 修改home 目录
  2. 我在 GitHub 上都见过哪些沙雕项目?
  3. 使用指针统计字符串中的数字字符的个数
  4. python 3 5的值_python3 语言特性5
  5. 知乎进化:对抗内容“熵增”胜算几何?
  6. 安卓 ce linux,手持移动数据终端的操作系统有哪些?Windows CE,Mobile和安卓各有什么优缺点?...
  7. SQL SERVER-约束
  8. chromedriver与chrome各版本及下载地址,截止到2018.5.30
  9. vue.js v-for
  10. 小马客服系统多种商户接入客服等!目前最好的客服系统 跟洽美差不多
  11. GDAL集成GEOS编译笔记
  12. 微信公众平台测试帐号申请及Token验证地址提供
  13. 微信小程序上传代码, Error: 分包大小超过限制,main package source size 4732KB exceed max limit 2MB
  14. DROOPYCTF WALKTHROUGH
  15. 【股票】融资融券基本概念
  16. 函数模板的特例化(专用化)以及类型含有const的特殊情况
  17. 使用Python下载MP3
  18. 计算机PPT中项目编号怎么弄,电脑技巧收藏家电脑基础设置幻灯片格式:项目符号和编号...
  19. 梦幻西游两个不同服务器的名字出现在跨服华山,系统会怎么处理,梦幻西游跨服决战华山测试报告【攻略达人】...
  20. %p 打印地址?它打印的是变量值!什么是格式化输出,指针与地址的区别

热门文章

  1. 基于搜狐新闻数据【完整版】训练中文word2vec模型
  2. Java对大文件MD5解密详解
  3. 由于系统错误 1114:动态连接库(DLL)初始化例程失败。(MySQL ODBC 5.3 Unicode Driver,c:\Program Files(x86)\MySQL\Connector
  4. Taro项目中设置了设计稿尺寸
  5. 1.居民身份证号码,由17位数字本体码,和1位数字校验码组成 2.判断用户输入的身份证号码是否合法 规则为:号码为18位,不能以0开头,前17位只可以是数字,最后一位可以是数字或‘X‘
  6. linux互信文件权限,Linux如何建立互信
  7. 7-2 新胖子公式 (5 分)
  8. python中、函数定义可以不包括以下一对圆括号_在python中,参数在函数定义的圆括号对内指定,用分号分割...
  9. 进程的基本概念及操作
  10. Android 点击键盘外 非输入框 关闭软键盘