SpringBoot集成SpringSecurity 快速上手+详细过程

1.新建工程,添加依赖,添加配置

        <!-- springbot web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springbot thymeleaf -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<!-- lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<!--Security依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<!-- MybatisPlus 核心库 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.1.0</version>
		</dependency>
		<!-- 引入阿里数据库连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
		<!-- StringUtilS工具 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<!-- JSON工具 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.68</version>
		</dependency>
		<!-- JWT依赖 -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-jwt</artifactId>
			<version>1.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
server:
  port: 80
spring:
  # 配置数据源
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.22.109:3306/spring_security_demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false
    username: base
    password: base
    type: com.alibaba.druid.pool.DruidDataSource
# JWT配置
jwt:
  # 密匙
  secret: JWTTokenSecret
  # 名称
  tokenName: jwt_token
  # 前缀
  tokenPrefix: pJrwitx-
  # 过期时间 : 单位秒
  expirationTime: 86400
  # 不需要认证的接口
  antMatchers: /login/**,/logout,/favicon.ico
# Mybatis-plus相关配置
mybatis-plus:
  # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath:mapper/*.xml
  # 以下配置均有默认值,可以不设置
  global-config:
    db-config:
      #主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: AUTO
      #字段策略 IGNORED:"忽略判断"  NOT_NULL:"非 NULL 判断")  NOT_EMPTY:"非空判断"
      field-strategy: NOT_EMPTY
      #数据库类型
      db-type: MYSQL
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 返回map时true:当查询数据为空时字段返回为null,false:不加这个查询数据为空时,字段将被隐藏
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.数据库创建,数据导入

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu`  (
  `menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限名称',
  `permission` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限标识',
  PRIMARY KEY (`menu_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 87 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '权限表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES (1, '查看用户信息', 'sys:user:info');
INSERT INTO `sys_menu` VALUES (2, '查看所有权限', 'sys:menu:info');
INSERT INTO `sys_menu` VALUES (3, '查看所有角色', 'sys:role:info');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (
  `role_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
  PRIMARY KEY (`role_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, 'ADMIN');
INSERT INTO `sys_role` VALUES (2, 'USER');

-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu`;
CREATE TABLE `sys_role_menu`  (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `role_id` bigint(11) NULL DEFAULT NULL COMMENT '角色ID',
  `menu_id` bigint(11) NULL DEFAULT NULL COMMENT '权限ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色与权限关系表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
INSERT INTO `sys_role_menu` VALUES (1, 1, 1);
INSERT INTO `sys_role_menu` VALUES (2, 1, 2);
INSERT INTO `sys_role_menu` VALUES (3, 1, 3);
INSERT INTO `sys_role_menu` VALUES (4, 2, 1);

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `user_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `status` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '状态 PROHIBIT:禁用   NORMAL:正常',
  PRIMARY KEY (`user_id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统用户表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$5T851lZ7bc2U87zjt/9S6OkwmLW62tLeGLB2aCmq3XRZHA7OI7Dqa', 'NORMAL');
INSERT INTO `sys_user` VALUES (2, 'user', '$2a$10$szHoqQ64g66PymVJkip98.Fap21Csy8w.RD8v5Dhq08BMEZ9KaSmS', 'NORMAL');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`  (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `user_id` bigint(11) NULL DEFAULT NULL COMMENT '用户ID',
  `role_id` bigint(11) NULL DEFAULT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户与角色关系表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (1, 1, 1);
INSERT INTO `sys_user_role` VALUES (2, 2, 2);

SET FOREIGN_KEY_CHECKS = 1;

3.添加实体类,service,dao

  ①实体类:SysUser

/**
 * 
 * @Description 系统用户实体类 
 *
 */
@Setter
@Getter
@TableName("sys_user")
public class SysUser implements Serializable{

	private static final long serialVersionUID = 1L;
	
	/**
	 * 用户ID
	 */
	@TableId
	private Long userId;
	
	/**
	 * 用户名
	 */
	private String username;
	
	/**
	 * 密码
	 */
	private String password;
	
	/**
	 * 状态:NORMAL正常  PROHIBIT禁用
	 */
	private String status;
	
}

   ②实体类:SysRole

/**
 * 
 * @Description 系统角色实体类 
 *
 */
@Setter
@Getter
@TableName("sys_role")
public class SysRole implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 角色ID
	 */
	@TableId
	private Long roleId;
	
	/**
	 * 角色名称
	 */
	private String roleName;
}

 ②实体类:SysMenu

/**
 * 
 * @Description 系统权限实体类
 *
 */
@Setter
@Getter
@TableName("sys_menu")
public class SysMenu implements Serializable {
	
	private static final long serialVersionUID = 1L;

	/**
	 * 权限ID
	 */
	@TableId
	private Long menuId;

	/**
	 * 权限名称
	 */
	private String name;

	/**
	 * 权限标识
	 */
	private String permission;
}

②实体类:SysUserRole,SysRoleMenu

/**
 * 
 * @Description 系统用戶于系統角色关系实体类
 *
 */
@Setter
@Getter
@TableName("sys_user_role")
public class SysUserRole implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * ID
	 */
	@TableId
	private Long id;

	/**
	 * 用户ID
	 */
	private Long userId;

	/**
	 * 角色ID
	 */
	private Long roleId;
}

④Dao层

/**
 * 
 * @Description 系统用户DAO层
 *
 */
@Mapper
public interface SysUserDao extends BaseMapper<SysUser> {
	
	/**
	 * 
	 * @Description 根据用户id查询角色集合 
	 * 
	 * @param userId 用户id
	 * @return List<SysRole> 角色集合
	 */
	List<SysRole> selectSysRolesByUserId(Long userId);
	
	/**
	 * 
	 * @Description 根据用户id查询权限集合 
	 * 
	 * @param userId 用户id
	 * @return List<SysMenu> 权限集合
	 */
	List<SysMenu> selectSysMenusByUserId(Long userId);
}

<!-- mapper -->
	
	<!-- 查询用户所有角色 -->
	<select id="selectSysRolesByUserId" resultType="com.bch.javapro.entity.SysMenu" 
        parameterType="long">
		SELECT sr.* FROM sys_role sr
		LEFT JOIN sys_user_role se ON se.role_id = sr.role_id
		WHERE se.user_id = #{userId}
	</select>
	
	<!-- 查询用户的所有权限 -->
	<select id="selectSysMenusByUserId" resultType="com.bch.javapro.entity.SysRole" 
        parameterType="long">
		SELECT DISTINCT m.* FROM sys_user_role ur
			LEFT JOIN sys_role_menu rm ON ur.role_id = rm.role_id
			LEFT JOIN sys_menu m ON rm.menu_id = m.menu_id
		WHERE ur.user_id = #{userId}
	</select>

<!-- mapper -->

  ⑤service层

/**
 * 
 * @Description 系统用户业务层接口 
 *
 */
public interface SysUserService extends IService<SysUser>{

	/**
	 * 
	 * @Description 根据用户名查询用户实体
	 * 
	 * @param username 用户名
	 * @return SysUser 用户实体
	 */
	SysUser selectUserByUsername(String username);
	
	/**
	 * 
	 * @Description 根据用户id查询角色集合
	 * 
	 * @param userId 用户id
	 * @return List<SysRole> 角色集合
	 */
	List<SysRole> selectSysRolesByUserId(Long userId);
	
	/**
	 * 
	 * @Description 根据用户id查询权限集合
	 * 
	 * @param userId 用户id
	 * @return List<SysMenu> 权限集合
	 */
	List<SysMenu> selectMenusByUserId(Long userId);
	
}

/**
 * 
 * @Description 系统用户业务层实现 
 *
 */
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserService{

	@Override
	public SysUser selectUserByUsername(String username) {
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
		queryWrapper.lambda().eq(SysUser::getUsername, username);
		return this.baseMapper.selectOne(queryWrapper);
	}

	@Override
	public List<SysRole> selectSysRolesByUserId(Long userId) {
		return this.baseMapper.selectSysRolesByUserId(userId);
	}

	@Override
	public List<SysMenu> selectMenusByUserId(Long userId) {
		return this.selectMenusByUserId(userId);
	}
	
}

4.security相关类的实现

  ①UserDetails的实现类

/**
 * 
 * @Description 自定义SpringSecurity的用户实体类 
 *
 */
@Data
public class SelfUserDetails implements Serializable, UserDetails {

	private static final long serialVersionUID = 1L;

	/**
	 * 用户ID
	 */
	private Long userId;

	/**
	 * 用户名
	 */
	private String username;

	/**
	 * 密码
	 */
	private String password;

	/**
	 * 状态:NORMAL正常 PROHIBIT禁用
	 */
	private String status;

	/**
	 * 用户角色
	 */
	private Collection<GrantedAuthority> authorities;

	/**
	 * 账户是否过期
	 */
	private boolean isAccountNonExpired = false;

	/**
	 * 账户是否被锁定
	 */
	private boolean isAccountNonLocked = false;

	/**
	 * 证书是否过期
	 */
	private boolean isCredentialsNonExpired = false;

	/**
	 * 账户是否有效
	 */
	private boolean isEnabled = true;

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}

	@Override
	public boolean isAccountNonExpired() {
		return isAccountNonExpired;
	}

	@Override
	public boolean isAccountNonLocked() {
		return isAccountNonLocked;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return isCredentialsNonExpired;
	}

	@Override
	public boolean isEnabled() {
		return isEnabled;
	}

}

  ②UserDetailsService实现类

/**
 * 
 * @Description 自定义SpringSecurity用户的业务实现类 
 *
 */
@Component
public class SelfUserDetailsService implements UserDetailsService {

	@Autowired
	private SysUserService sysUserService;
	
	/**
	 * 获取用户信息
	 */
	@Override
	public SelfUserDetails loadUserByUsername(String username) throws             
        UsernameNotFoundException {
		SysUser sysUser = sysUserService.selectUserByUsername(username);
		if(null != sysUser) {
			SelfUserDetails selfUserDetails = new SelfUserDetails();
			BeanUtils.copyProperties(sysUser, selfUserDetails);
			return selfUserDetails;
		}
		return null;
	}
	
}

  ③自定义登录验证

/**
 * 
 * @Description 自定义登录验证
 *
 */
@Component
public class SelfAuthenticationProvider implements AuthenticationProvider {

	@Autowired
	private SelfUserDetailsService selfUserDetailsService;

	@Autowired
	private SysUserService sysUserService;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		// 用户名
		String username = String.valueOf(authentication.getPrincipal());
		// 密码
		String password = String.valueOf(authentication.getCredentials());

		// 获取用户
		SelfUserDetails selfUserDetails = selfUserDetailsService.loadUserByUsername(username);

		// 用户不存在
		if (null == selfUserDetails) {
			throw new UsernameNotFoundException("用户名不存在");
		}
		// 密码不正确
		if (!new BCryptPasswordEncoder().matches(password, selfUserDetails.getPassword())) {
			throw new BadCredentialsException("密码不正确");
		}
		// 用户已被冻结
		if (StringUtils.equals("PROHIBIT", selfUserDetails.getStatus())) {
			throw new LockedException("该用户已被冻结");
		}

		// 验证通过,查询用户角色
		List<SysRole> sysRoles = sysUserService.selectSysRolesByUserId(selfUserDetails.getUserId());

		// 将角色设置给自定义的UserDetails
		Set<GrantedAuthority> authorities = new HashSet<>();
		if (null != sysRoles && sysRoles.size() > 0) {
			for (SysRole sysRole : sysRoles) {
				authorities.add(new SimpleGrantedAuthority("ROLE_" + sysRole.getRoleName()));
			}
		}
		selfUserDetails.setAuthorities(authorities);

		// 登录管理
		return new UsernamePasswordAuthenticationToken(selfUserDetails, password, authorities);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return true;
	}

}

④自定义过滤器,验证token

  首先,添加JWT配置类

/**
 * 
 * @Description JWT配置类 
 *
 */
@Getter
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JWTConfig {
	
	/**
	 * 密钥
	 */
	public static String secret;
	
	/**
	 * 名称
	 */
	public static String tokenName;
	
	/**
	 * 前缀
	 */
	public static String tokenPrefix;
	
	/**
	 * 过期时间 : 单位秒
	 */
	public static Long expirationTime;
	
	/**
	 * 不需要认证的接口
	 */
	public static String antMatchers;
	
	public void setSecret(String secret) {
		JWTConfig.secret = secret;
	}

	public void setTokenName(String tokenName) {
		JWTConfig.tokenName = tokenName;
	}

	public void setTokenPrefix(String tokenPrefix) {
		JWTConfig.tokenPrefix = tokenPrefix;
	}

	public void setExpirationTime(Long expirationTime) {
		JWTConfig.expirationTime = expirationTime;
	}

	public void setAntMatchers(String antMatchers) {
		JWTConfig.antMatchers = antMatchers;
	}
	
}

 自定义过滤器如下:

/**
 * 
 * @Description 自定义过滤器,验证token
 *
 */
public class SelfAuthenticationFilter extends BasicAuthenticationFilter {

	public SelfAuthenticationFilter(AuthenticationManager authenticationManager) {
		super(authenticationManager);
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 获取token
		String token = request.getHeader(JWTConfig.tokenName);

		// token存在,并且前缀正确
		if (StringUtils.isNotBlank(token) && token.startsWith(JWTConfig.tokenPrefix)) {
			// 截取前缀
			token = token.replace(JWTConfig.tokenPrefix, "");
			// 解析JWT
			Claims claims = Jwts.parser().setSigningKey(JWTConfig.secret).parseClaimsJws(token).getBody();
			// 获取用户
			String username = claims.getSubject();
			String userId = claims.getId();
			if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(userId)) {
				// 获取角色信息
				String authority = claims.get("authorities").toString();
				if (StringUtils.isNotBlank(authority)) {
					List<GrantedAuthority> authorities = new ArrayList<>();
					@SuppressWarnings("unchecked")
					List<Map<String, String>> authorityMap = JSONObject.parseObject(authority, ArrayList.class);
					for (Map<String, String> role : authorityMap) {
						if (StringUtils.isNotBlank(role.get("authority"))) {
							authorities.add(new SimpleGrantedAuthority(role.get("authority")));
						}
					}
					// 设置Authentication
					SelfUserDetails selfUserDetails = new SelfUserDetails();
					selfUserDetails.setUsername(username);
					selfUserDetails.setUserId(Long.parseLong(userId));
					selfUserDetails.setAuthorities(authorities);
					SecurityContextHolder.getContext().setAuthentication(
							new UsernamePasswordAuthenticationToken(selfUserDetails, userId, authorities));
				} 
			} 
		} 
		
		chain.doFilter(request, response);
	}
}

5.Security的配置(重中之重)

/**
 * 
 * @Description SpringSecurity配置类
 *
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private SelfAuthenticationProvider selfAuthenticationProvider;

	/**
	 * 加密方式
	 */
	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	/**
	 * 使用自定义的登陆验证
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(selfAuthenticationProvider);
	}
	
	/**
	 * 配置控制逻辑
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				// 不进行验证的资源地址
				.antMatchers(JWTConfig.antMatchers.split(",")).permitAll()
				// 其他都需要验证
				.anyRequest().authenticated().and()
				.formLogin()
				// 配置登陆地址
//				.loginPage("login.html")
				// 配置登陆接口地址
				.loginProcessingUrl("/login/userLogin")
				// 请求成功处理
				.successHandler(new AuthenticationSuccessHandler() {
					@Override
					public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
							Authentication authentication) throws IOException, ServletException {
						SelfUserDetails selfUserDetails = (SelfUserDetails) authentication.getPrincipal();
						String token = JWTConfig.tokenPrefix + JWTUtil.createToken(selfUserDetails);
						System.out.println("登陆成功:token=" + token);
						PrintWriter out = null;
						try {
							response.setCharacterEncoding("UTF-8");
							response.setContentType("application/json");
							out = response.getWriter();
							out.println(token);
						} finally {
							if (null != out) {
								out.flush();
								out.close();
							}
						}
					}
				})
				//.successForwardUrl("/hi")
				.failureHandler(new AuthenticationFailureHandler() {
					@Override
					public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
							AuthenticationException exception) throws IOException, ServletException {
						System.out.println("请求失败啦");
					}
				})
				.and()
				.logout()
				// 配置登出地址
				.logoutUrl("/logout").and().cors().and().csrf();
		// 不使用session
		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
		// 禁用缓存
		http.headers().cacheControl();
		// 添加自定义过滤器
		http.addFilter(new SelfAuthenticationFilter(authenticationManager()));
	}
}

配置类使用到的JWTUtil类

/**
 * 
 * @Description JWT工具类 
 *
 */
public class JWTUtil {

	/**
	 * @Description 私有化构造器
	 */
	private JWTUtil() {
	}
	
	/**
	 * 
	 * @Description 生成token 
	 * 
	 * @param selfUserDetails 用户实体
	 * @return token
	 */
	public static String createToken(SelfUserDetails selfUserDetails) {
		String token = Jwts.builder()
				.setId(String.valueOf(selfUserDetails.getUserId()))
				.setSubject(selfUserDetails.getUsername())
				.setIssuedAt(new Date())
				.setIssuer("")
				.claim("authorities", JSON.toJSONString(selfUserDetails.getAuthorities()))
				.setExpiration(new Date(System.currentTimeMillis() + JWTConfig.expirationTime * 1000))
				.signWith(SignatureAlgorithm.HS512, JWTConfig.secret)
				.compact();
		return token;
	}
}

6.验证

  添加controller

@RestController
public class HiController {

	// 所有用户都可以访问
	@GetMapping("/hi")
	public String hi() {
		return "hi";
	}
	
	// ADMIN用户都可以访问
	@GetMapping("/adminhi")
	@PreAuthorize("hasRole('ADMIN')")
	public String adminHi() {
		return "admin: hi";
	}
	
	// USER用户都可以访问
	@GetMapping("/userhi")
	@PreAuthorize("hasRole('USER')")
	public String userHi() {
		return "user: hi";
	}
}

  ①浏览器请求http://localhost/hi,发现为登陆,自动调整到登陆画面

②用户登陆,上述sql中admin,user的密码均为123456,获得token

③使用postman访问http://localhost/hi,header添加token

 本例使用的是admin用户登陆的,访问http://localhost/adminhi,http://localhost/userhi的结果如下:

补充,权限继承

配置类添加

    /**
	 * 权限继承
	 */
	@Bean
	RoleHierarchy roleHierarchy() {
		RoleHierarchyImpl impl = new RoleHierarchyImpl();
		impl.setHierarchy("ROLE_ADMIN > ROLE_USER");
		return impl;
	}

admin用户访问http://localhost/userhi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值