JWT 框架图如下, 来自博客https://blog.csdn.net/shehun1/article/details/45394405 个人觉得还不错..

在开发中Spring boot 启用

加载WebSecurityConfig

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {// 使用自定义身份验证组件auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 禁用 csrf, 由于使用的是JWT,我们这里不需要csrf
        http.cors().and().csrf().disable().authorizeRequests()// 跨域预检请求.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()// web jars.antMatchers("/webjars/**").permitAll()// 查看SQL监控(druid).antMatchers("/druid/**").permitAll()// 首页和登录页面.antMatchers("/").permitAll().antMatchers("/login").permitAll()// swagger.antMatchers("/swagger-ui.html").permitAll().antMatchers("/swagger-resources").permitAll().antMatchers("/v2/api-docs").permitAll().antMatchers("/webjars/springfox-swagger-ui/**").permitAll()// 验证码.antMatchers("/captcha.jpg**").permitAll()// 服务监控.antMatchers("/actuator/**").permitAll()// 其他所有请求需要身份认证
            .anyRequest().authenticated();// 退出登录处理器http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());// token验证过滤器http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);}@Bean@Overridepublic AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}}

第二配置Security实现

1:  继承 DaoAuthenticationProvider 类
public class JwtAuthenticationProvider extends DaoAuthenticationProvider {public JwtAuthenticationProvider(UserDetailsService userDetailsService) {setUserDetailsService(userDetailsService);}@Overrideprotected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {if (authentication.getCredentials() == null) {logger.debug("Authentication failed: no credentials provided");throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}String presentedPassword = authentication.getCredentials().toString();String salt = ((JwtUserDetails) userDetails).getSalt();// 覆写密码验证逻辑if (!new PasswordEncoder(salt).matches(userDetails.getPassword(), presentedPassword)) {logger.debug("Authentication failed: password does not match stored value");throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}}}

2:实现 UserDetails 接口

public class JwtUserDetails implements UserDetails {private static final long serialVersionUID = 1L;private String username;private String password;private String salt;private Collection<? extends GrantedAuthority> authorities;JwtUserDetails(String username, String password, String salt, Collection<? extends GrantedAuthority> authorities) {this.username = username;this.password = password;this.salt = salt;this.authorities = authorities;}@Overridepublic String getUsername() {return username;}@JsonIgnore@Overridepublic String getPassword() {return password;}public String getSalt() {return salt;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return authorities;}@JsonIgnore@Overridepublic boolean isAccountNonExpired() {return true;}@JsonIgnore@Overridepublic boolean isAccountNonLocked() {return true;}@JsonIgnore@Overridepublic boolean isCredentialsNonExpired() {return true;}@JsonIgnore@Overridepublic boolean isEnabled() {return true;}}

3: 实现 UserDetailsService 接口
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate SysUserService sysUserService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = sysUserService.findByName(username);if (user == null) {throw new UsernameNotFoundException("该用户不存在");}// 用户权限列表,根据用户拥有的权限标识与如 @PreAuthorize("hasAuthority('sys:menu:view')") 标注的接口对比,决定是否可以调用接口Set<String> permissions = sysUserService.findPermissions(user.getName());List<GrantedAuthority> grantedAuthorities = permissions.stream().map(GrantedAuthorityImpl::new).collect(Collectors.toList());return new JwtUserDetails(user.getName(), user.getPassword(), user.getSalt(), grantedAuthorities);}
}

4: 认证对象 继承 GrantedAuthority 
public class GrantedAuthorityImpl implements GrantedAuthority {private static final long serialVersionUID = 1L;private String authority;public GrantedAuthorityImpl(String authority) {this.authority = authority;}public void setAuthority(String authority) {this.authority = authority;}@Overridepublic String getAuthority() {return this.authority;}
}

5:JWT 的认证令牌对象 用于登录时创建一个

package com.louis.kitty.admin.security;import java.util.Collection;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;/*** 自定义令牌对象* @author Louis* @date Nov 21, 2018*/
public class JwtAuthenticatioToken extends UsernamePasswordAuthenticationToken {private static final long serialVersionUID = 1L;private String token;public JwtAuthenticatioToken(Object principal, Object credentials){super(principal, credentials);}public JwtAuthenticatioToken(Object principal, Object credentials, String token){super(principal, credentials);this.token = token;}public JwtAuthenticatioToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities, String token) {super(principal, credentials, authorities);this.token = token;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}public static long getSerialversionuid() {return serialVersionUID;}}

6:配置Security工具类

package com.louis.kitty.admin.util;import javax.servlet.http.HttpServletRequest;import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;import com.louis.kitty.admin.security.JwtAuthenticatioToken;/*** Security相关操作* @author Louis* @date Nov 20, 2018*/
public class SecurityUtils {/*** 系统登录认证* @param request* @param username* @param password* @param authenticationManager* @return*/public static JwtAuthenticatioToken login(HttpServletRequest request, String username, String password, AuthenticationManager authenticationManager) {JwtAuthenticatioToken token = new JwtAuthenticatioToken(username, password);token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));// 执行登录认证过程Authentication authentication = authenticationManager.authenticate(token);// 认证成功存储认证信息到上下文
        SecurityContextHolder.getContext().setAuthentication(authentication);// 生成令牌并返回给客户端
        token.setToken(JwtTokenUtils.generateToken(authentication));return token;}/*** 获取令牌进行认证* @param request*/public static void checkAuthentication(HttpServletRequest request) {// 获取令牌并根据令牌获取登录认证信息Authentication authentication = JwtTokenUtils.getAuthenticationeFromToken(request);// 设置登录认证信息到上下文
        SecurityContextHolder.getContext().setAuthentication(authentication);}/*** 获取当前用户名* @return*/public static String getUsername() {String username = null;Authentication authentication = getAuthentication();if(authentication != null) {Object principal = authentication.getPrincipal();if(principal != null && principal instanceof UserDetails) {username = ((UserDetails) principal).getUsername();}}return username;}/*** 获取用户名* @return*/public static String getUsername(Authentication authentication) {String username = null;if(authentication != null) {Object principal = authentication.getPrincipal();if(principal != null && principal instanceof UserDetails) {username = ((UserDetails) principal).getUsername();}}return username;}/*** 获取当前登录信息* @return*/public static Authentication getAuthentication() {if(SecurityContextHolder.getContext() == null) {return null;}Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return authentication;}}

7: 登录处理

@Autowiredprivate AuthenticationManager authenticationManager;
// 系统登录认证
JwtAuthenticatioToken token = SecurityUtils.login(request, username, password, authenticationManager);

8: 生成Token工具类

package com.louis.kitty.admin.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;import com.louis.kitty.admin.security.GrantedAuthorityImpl;
import com.louis.kitty.admin.security.JwtAuthenticatioToken;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;/*** JWT工具类* @author Louis* @date Nov 20, 2018*/
public class JwtTokenUtils implements Serializable {private static final long serialVersionUID = 1L;/*** 用户名称*/private static final String USERNAME = Claims.SUBJECT;/*** 创建时间*/private static final String CREATED = "created";/*** 权限列表*/private static final String AUTHORITIES = "authorities";/*** 密钥*/private static final String SECRET = "abcdefgh";/*** 有效期12小时*/private static final long EXPIRE_TIME = 12 * 60 * 60 * 1000;/*** 生成令牌** @param userDetails 用户* @return 令牌*/public static String generateToken(Authentication authentication) {Map<String, Object> claims = new HashMap<>(3);claims.put(USERNAME, SecurityUtils.getUsername(authentication));claims.put(CREATED, new Date());claims.put(AUTHORITIES, authentication.getAuthorities());return generateToken(claims);}/*** 从数据声明生成令牌** @param claims 数据声明* @return 令牌*/private static String generateToken(Map<String, Object> claims) {Date expirationDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, SECRET).compact();}/*** 从令牌中获取用户名** @param token 令牌* @return 用户名*/public static String getUsernameFromToken(String token) {String username;try {Claims claims = getClaimsFromToken(token);username = claims.getSubject();} catch (Exception e) {username = null;}return username;}/*** 根据请求令牌获取登录认证信息* @param token 令牌* @return 用户名*/public static Authentication getAuthenticationeFromToken(HttpServletRequest request) {Authentication authentication = null;// 获取请求携带的令牌String token = JwtTokenUtils.getToken(request);if(token != null) {// 请求令牌不能为空if(SecurityUtils.getAuthentication() == null) {// 上下文中Authentication为空Claims claims = getClaimsFromToken(token);if(claims == null) {return null;}String username = claims.getSubject();if(username == null) {return null;}if(isTokenExpired(token)) {return null;}Object authors = claims.get(AUTHORITIES);List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();if (authors != null && authors instanceof List) {for (Object object : (List) authors) {authorities.add(new GrantedAuthorityImpl((String) ((Map) object).get("authority")));}}authentication = new JwtAuthenticatioToken(username, null, authorities, token);} else {if(validateToken(token, SecurityUtils.getUsername())) {// 如果上下文中Authentication非空,且请求令牌合法,直接返回当前登录认证信息authentication = SecurityUtils.getAuthentication();}}}return authentication;}/*** 从令牌中获取数据声明** @param token 令牌* @return 数据声明*/private static Claims getClaimsFromToken(String token) {Claims claims;try {claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();} catch (Exception e) {claims = null;}return claims;}/*** 验证令牌* @param token* @param username* @return*/public static Boolean validateToken(String token, String username) {String userName = getUsernameFromToken(token);return (userName.equals(username) && !isTokenExpired(token));}/*** 刷新令牌* @param token* @return*/public static String refreshToken(String token) {String refreshedToken;try {Claims claims = getClaimsFromToken(token);claims.put(CREATED, new Date());refreshedToken = generateToken(claims);} catch (Exception e) {refreshedToken = null;}return refreshedToken;}/*** 判断令牌是否过期** @param token 令牌* @return 是否过期*/public static Boolean isTokenExpired(String token) {try {Claims claims = getClaimsFromToken(token);Date expiration = claims.getExpiration();return expiration.before(new Date());} catch (Exception e) {return false;}}/*** 获取请求token* @param request* @return*/public static String getToken(HttpServletRequest request) {String token = request.getHeader("Authorization");String tokenHead = "Bearer ";if(token == null) {token = request.getHeader("token");} else if(token.contains(tokenHead)){token = token.substring(tokenHead.length());} if("".equals(token)) {token = null;}return token;}}

方法调用权限使用

转载于:https://www.cnblogs.com/eason-d/p/10722780.html

Spring Security 理解小记相关推荐

  1. Spring Security 实战干货: RBAC权限控制概念的理解

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 码农小胖哥 来源 | 公众号「码农小胖哥」 1 ...

  2. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  3. 【闲聊杂谈】深入理解Spring Security设计原理

    1.什么是Spring Security 顾名思义,Security的意思是安全,本质上就是一个很纯粹的权限管理框架,提供认证和授权两大核心功能.在目前主流的Spring生态中的项目,说到安全框架,基 ...

  4. Spring Security并没有那么难嗷 简单理解OAuth2.0

    文章目录 1. 基本概念 1.1 什么是认证 1.2 什么是会话 1.3 什么是授权 1.4 授权的数据模型 1.5 RBAC 1.5.1 基于角色的访问控制 1.5.2 基于资源的访问控制 2. 基 ...

  5. 理解Spring Security中permitAll()和anonymous()的区别

    从 Spring文档: 采用"默认拒绝"通常被认为是良好的安全实践,您可以明确指定允许的内容并禁止其他所有内容.定义未经身份验证的用户可以访问的内容是类似的情况,尤其是对于 Web ...

  6. Spring Security简单理解

    最近在学习Spring Security,于是就写了这篇Spring Security的博客来记录自己的学习中的一些总结,本文主要是一些简单的原理分析,没有涉及很深的源码分析. 1. Spring S ...

  7. spring security 简单理解

    一.简介 Spring Security 是 Spring 家族中的一个安全管理框架. 一般来说,常见的安全管理技术栈的组合是这样的: SSM + Shiro Spring Boot/Spring C ...

  8. Spring Security 实战干货:自定义异常处理

    Spring Security 实战干货:自定义异常处理 转自:https://www.cnblogs.com/felordcn/p/12142514.html 文章目录 1. 前言 2. Sprin ...

  9. Spring Security 中最流行的权限管理模型!

    前面和大家说了 ACL,讲了理论,也给了一个完整的案例,相信小伙伴们对于 ACL 权限控制模型都已经比较了解了. 本文我要和大家聊一聊另外一个非常流行的权限管理模型,那就是 RBAC. 1.RBAC ...

最新文章

  1. 软件测试培训:高薪测试技术要掌握哪些
  2. 脑与神经类开放数据库汇总
  3. 【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )
  4. 七周三次课(1月24日) 10.11 Linux网络相关 10.12 firewalld和netfilter 10.13 netfilter5表5链介绍 10.14 iptables语法...
  5. 致所有.Net者和有梦想的朋友们 - 共勉
  6. YBTOJ:染颜色(KDtree)
  7. ejb的maven_针对新手的Java EE7和Maven项目-第3部分-定义ejb服务和jpa实体模块
  8. 游戏笔记本计算机购买,2021大学生买电脑,容易犯的七种错误!游戏本和轻薄本买哪个?...
  9. VMware NAT模式设置静态IP(可上网)
  10. 自学python-自学编程的6种方法,自学Python
  11. [Objective-C]用Block实现链式编程
  12. 开源有限元程序AsFem
  13. flask python 上传图片或头像
  14. 一位资深程序员大牛给予Java初学者的学习建议
  15. Filler Cell 与 Metal Fill差异
  16. 【泛微E-Mobile】管理员是否可以监控群聊
  17. idea如何连接达梦数据库
  18. TPshop项目-功能测试(2)
  19. Android8.0,允许安装未知来源
  20. 三分钟读懂:云计算与虚拟化的关系

热门文章

  1. 让apache支持mysql_Apache+PHP+Mysql环境搭建之三:配置Apache支持PHP
  2. android fragment 教程,Android app开发中的Fragment入门学习教程
  3. vos2009 校验版本超时_开源多云应用平台 Choerodon猪齿鱼发布0.14版本
  4. python远程linux服务器执行命令_基于使用paramiko执行远程linux主机命令(详解)
  5. pycharm去除波浪线的方法
  6. 计算尖峰电流的目的_干货 | 谈谈RCD的计算方法
  7. 安卓9.0官方系统升级包_想升级鸿蒙系统都来看看!华为新系统升级名单曝光:有你手机吗?...
  8. linux删除eth2设备_Linux卸载/删除多余网卡
  9. 目前人工智能技术趋势如何?
  10. mac下的git的安装与简单的配置