spring-security实现的token授权
在我的用户密码授权文章里介绍了spring-security的工作过程,不了解的同学,可以先看看用户密码授权这篇文章,在
用户密码授权模式里,主要是通过一个登陆页进行授权,然后把授权对象写到session里,它主要用在mvc框架里,而对于webapi来说,一般不会采用这种方式,对于webapi
来说,一般会用jwt授权方式,就是token授权码的方式,每访问api接口时,在http头上带着你的token码,而大叔自己也写了一个简单的jwt授权模式,下面介绍一下。
WebSecurityConfig授权配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* token过滤器.
*/
@Autowired
LindTokenAuthenticationFilter lindTokenAuthenticationFilter;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// 对于获取token的rest api要允许匿名访问
.antMatchers("/lind-auth/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
httpSecurity
.addFilterBefore(lindTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// 禁用缓存
httpSecurity.headers().cacheControl();
}
/**
* 密码生成策略.
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
授权接口login
对外开放的,需要提供用户名和密码为参数进行登陆,然后返回token码,当然也可以使用手机号和验证码登陆,授权逻辑是一样的,获取用户信息都是使用UserDetailsService,
然后开发人员根据自己的业务去重写loadUserByUsername来获取用户实体。
用户登陆成功后,为它授权及认证,这一步我们会在redis里建立token与用户名的关系。
@GetMapping(LOGIN)
public ResponseEntity<?> refreshAndGetAuthenticationToken(
@RequestParam String username,
@RequestParam String password) throws AuthenticationException {
return ResponseEntity.ok(generateToken(username, password));
}
/**
* 登陆与授权.
*
* @param username .
* @param password .
* @return
*/
private String generateToken(String username, String password) {
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
// Perform the security
final Authentication authentication = authenticationManager.authenticate(upToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Reload password post-security so we can generate token
final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 持久化的redis
String token = CommonUtils.encrypt(userDetails.getUsername());
redisTemplate.opsForValue().set(token, userDetails.getUsername());
return token;
}
LindTokenAuthenticationFilter代码
主要实现了对请求的拦截,获取http头上的Authorization元素,token码就在这个键里,我们的token都是采用通用的Bearer开头,当你的token没有过期时,会
存储在redis里,key就是用户名的md5码,而value就是用户名,当拿到token之后去数据库或者缓存里拿用户信息进行授权即可。
/**
* token filter bean.
*/
@Component
public class LindTokenAuthenticationFilter extends OncePerRequestFilter {
@Autowired
RedisTemplate<String, String> redisTemplate;
String tokenHead = "Bearer ";
String tokenHeader = "Authorization";
@Autowired
private UserDetailsService userDetailsService;
/**
* token filter.
*
* @param request .
* @param response .
* @param filterChain .
*/
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader(this.tokenHeader);
if (authHeader != null && authHeader.startsWith(tokenHead)) {
final String authToken = authHeader.substring(tokenHead.length()); // The part after "Bearer "
if (authToken != null && redisTemplate.hasKey(authToken)) {
String username = redisTemplate.opsForValue().get(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
//可以校验token和username是否有效,目前由于token对应username存在redis,都以默认都是有效的
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
request));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request, response);
}
测试token授权
get:http://localhost:8080/lind-demo/login?username=admin&password=123
post:http://localhost:8080/lind-demo/user/add
Content-Type:application/json
Authorization:Bearer 21232F297A57A5A743894A0E4A801FC3
spring-security实现的token授权的更多相关文章
- 使用Redis作为Spring Security OAuth2的token存储
写在前边 本文对Spring Security OAuth2的token使用Redis保存,相比JWT实现的token存储,Redis可以随时吊销access_token,并且Redis响应速度很快, ...
- Spring Security实现OAuth2.0授权服务 - 进阶版
<Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Sec ...
- Spring Security OAuth2.0认证授权二:搭建资源服务
在上一篇文章[Spring Security OAuth2.0认证授权一:框架搭建和认证测试](https://www.cnblogs.com/kuangdaoyizhimei/p/14250374. ...
- Spring Security OAuth2.0认证授权三:使用JWT令牌
Spring Security OAuth2.0系列文章: Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二: ...
- Spring Security OAuth2.0认证授权四:分布式系统认证授权
Spring Security OAuth2.0认证授权系列文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授 ...
- Spring Security OAuth2.0认证授权五:用户信息扩展到jwt
历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...
- Spring Security OAuth2.0认证授权六:前后端分离下的登录授权
历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...
- Spring Security OAuth 格式化 token 输出
个性化token 背景 上一篇文章<Spring Security OAuth 个性化token(一)>有提到,oauth2.0 接口默认返回的报文格式如下: { "ac ...
- 使用JWT作为Spring Security OAuth2的token存储
序 Spring Security OAuth2的demo在前几篇文章中已经讲过了,在那些模式中使用的都是RemoteTokenService调用授权服务器来校验token,返回校验通过的用户信息供上 ...
- Spring Security实现OAuth2.0授权服务 - 基础版
一.OAuth2.0协议 1.OAuth2.0概述 OAuth2.0是一个关于授权的开放网络协议. 该协议在第三方应用与服务提供平台之间设置了一个授权层.第三方应用需要服务资源时,并不是直接使用用户帐 ...
随机推荐
- 【树形dp】Bzoj3391 [Usaco2004 Dec]Tree Cutting网络破坏
Description 约翰意识到贝茜建设网络花费了他巨额的经费,就把她解雇了.贝茜很愤怒,打算狠狠报 复.她打算破坏刚建成的约翰的网络. 约翰的网络是树形的,连接着N(1≤N≤1000 ...
- 【二分贪心】Bzoj3969 [WF2013] Low Power
Description 有n个机器,每个机器有2个芯片,每个芯片可以放k个电池. 每个芯片能量是k个电池的能量的最小值. 两个芯片的能量之差越小,这个机器就工作的越好. 现在有2nk个电池,已知它们的 ...
- iscc2018(一只猫的心思)
由于这一个杂项类没有更新,所以今天特地来写一下博文.希望能够帮助到你们!!!! 其他关于杂项类的解析,可以查看(https://blog.csdn.net/qq_41187256/article/de ...
- Postman-----Response body:JSON value check的使用介绍
Response body:JSON value check :检查Response返回的body的某个字段所对应的值是否与预期结果的值相等 1.直接点击 Response body:JSON ...
- appium 运行报错:...... Attempt to re-install io.appium.settings without first uninstalling解决方案
报错形式: Failed to install D:\AutoTest\appium\Appium\node_modules\appium\build\settings_apk\settings_ap ...
- 从零开始学 Web 之 CSS(三)链接伪类、背景、行高、盒子模型、浮动
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
- Spark学习之数据读取与保存总结(一)
一.动机 我们已经学了很多在 Spark 中对已分发的数据执行的操作.到目前为止,所展示的示例都是从本地集合或者普通文件中进行数据读取和保存的.但有时候,数据量可能大到无法放在一台机器中,这时就需要探 ...
- 从壹开始微服务 [ DDD ] 之十 ║领域驱动【实战篇·中】:命令总线Bus分发(一)
烽火 哈喽大家好,老张又见面了,这两天被各个平台的“鸡汤贴”差点乱了心神,博客园如此,简书亦如此,还好群里小伙伴及时提醒,路还很长,这些小事儿就随风而去吧,这周本不打算更了,但是被群里小伙伴“催稿”了 ...
- OpenResty 在又拍云容器平台中的应用
大家好,我是又拍云叶靖,今天主要分享 OpenResty 在又拍云容器平台中的应用.目前又拍云有很多产品,其中很多都使用了 OpenResty 技术,比如又拍云的 CDN .网关都是基于 OpenRe ...
- 一段简单的显示当前页面FPS的代码
写前端代码,尤其是做一个前端框架的时候,经常需要及时知道代码的大致性能,这时候如果能有个好的办法能一直看到当前页面的fps就好了. 整体思路是一秒有一千毫秒,先记录当前时间作为最后一次记录fps的时间 ...