最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

springboot

IT圈 admin 13浏览 0评论

springboot

一个简单的security安全登录示例

  1. 配置环境
    1. 添加pom依赖坐标
      <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version></parent><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency></dependencies>
    2.  application.yml文件配置
      server:port: 9999
      spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: rootmain:allow-bean-definition-overriding: trueredis:port: 6379host: 127.0.0.1
      logging:level:root: INFOorg.springframework.web.servlet.DispatcherServlet: DEBUGorg.springframework.cloud.sleuth: DEBUG
    3.  数据库就一张用户表(简单登录:用户表)
      SET NAMES utf8mb4;
      SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
      -- Table structure for tb_user
      -- ----------------------------
      DROP TABLE IF EXISTS `tb_user`;
      CREATE TABLE `tb_user`  (`id` int(11) NOT NULL,`account` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`role` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
      ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
      -- Records of tb_user
      -- ----------------------------
      INSERT INTO `tb_user` VALUES (1, '123456', 'admin', '$2a$10$gGKeupjLdvbaoYdAlz1MfuiT/4llYvGFU2QeQ..CQIhCXyqXekn5.', 'test');
      INSERT INTO `tb_user` VALUES (2, '789456', 'zhangsan', '$2a$10$gGKeupjLdvbaoYdAlz1MfuiT/4llYvGFU2QeQ..CQIhCXyqXekn5.', NULL);SET FOREIGN_KEY_CHECKS = 1;
    4. 编写统一返回类
      @Data
      @Accessors(chain = true)
      public class R {//成功状态位private Boolean success;//响应消息private String message;//响应码private Integer code;//响应数据private Object data;private static final String DEFAULT_SUCCESS_MESSAGE = "OK";private static final Integer DEFAULT_SUCCESS_CODE = 20000;private static final String DEFAULT_FALL_MESSAGE = "ERROR";private static final Integer DEFAULT_FALL_CODE = 50000;private R(Boolean success, String message, Integer code, Object data) {this.success = success;this.message = message;this.code = code;this.data = data;}public static R success(){R r = new R(true,DEFAULT_SUCCESS_MESSAGE,DEFAULT_SUCCESS_CODE,null);return r;}public static R success(String message){R r = new R(true,message,DEFAULT_SUCCESS_CODE,null);return r;}public static R success(Object data){R r = new R(true,DEFAULT_SUCCESS_MESSAGE,DEFAULT_SUCCESS_CODE,data);return r;}public static R success(String message,Object data){R r = new R(true,message,DEFAULT_SUCCESS_CODE,data);return r;}public static R fail(){R r = new R(false,DEFAULT_FALL_MESSAGE,DEFAULT_FALL_CODE,null);return r;}public static R fail(String message){R r = new R(false,message,DEFAULT_FALL_CODE,null);return r;}public static R fail(String message,Integer code){R r = new R(false,message,code,null);return r;}
      }
    5.  redis配置
      @Configuration
      public class RedisConfig {/*** retemplate相关配置* @param factory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();// 配置连接工厂template.setConnectionFactory(factory);//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);// 值采用json序列化template.setValueSerializer(jacksonSeial);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());// 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}}
  2.  创建实体类,实现接口UserDetails,实现获取权限方法
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true)
    public class UserBean implements UserDetails {private String account;private String username;private String password;private String role;@JSONField(serialize = false)private List<SimpleGrantedAuthority> authorities;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {if (authorities != null) {return authorities;}authorities = new ArrayList<>();if(null!=role){SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role);authorities.add(simpleGrantedAuthority);}return authorities;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
    }

  3.  创建mapper接口,编写sql语句
    @Mapper
    public interface UserBeanMapper {//根据账号查询用户信息@Select("select * from tb_user where account=#{account}")UserBean findUserById(@Param("account")String account);
    }
  4.  创建service层登录接口
    public interface UserBeanService {R login(String account,String password);
    }
  5.  实现service层接口
    @Service
    public class UserServiceImpl implements UserBeanService {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Overridepublic R login(String account, String password) {
    //创建用户身份验证UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(account, password);Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);if(null==authenticate){return R.fail("账户名或密码错误");}
    //以hash方式存储redis中redisTemplate.boundHashOps(account).put(account, JSON.toJSONString(authenticate.getPrincipal()));
    //设置redis过期时间redisTemplate.boundHashOps(account).expire(100000, TimeUnit.MILLISECONDS);return R.success(JwtUtil.createJWT(account));}
    }
  6.  创建controller层
    @RestController
    public class UserBeanController {@Autowiredprivate UserBeanService userBeanService;//登录@PostMapping("/login")public R login(@RequestParam("account") String account, @RequestParam("password") String password){return userBeanService.login(account,password);}//权限测试@GetMapping("/test")@PreAuthorize("hasAuthority('test')")public R test(){return R.success("这是一条提示消息","test");}
    }

 security相关代码配置

  1. 这里使用jwt令牌,创建jwt工具类
    /*** JWT工具类*/
    public class JwtUtil {//有效期为public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000  一个小时//设置秘钥明文public static final String JWT_KEY = "mingwen";public static String getUUID(){String token = UUID.randomUUID().toString().replaceAll("-", "");return token;}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @return*/public static String createJWT(String subject) {JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间return builder.compact();}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @param ttlMillis token超时时间* @return*/public static String createJWT(String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间return builder.compact();}private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);return Jwts.builder().setId(uuid)              //唯一的ID.setSubject(subject)   // 主题  可以是JSON数据.setIssuer("sanyue")     // 签发者.setIssuedAt(now)      // 签发时间.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥.setExpiration(expDate);}/*** 创建token* @param id* @param subject* @param ttlMillis* @return*/public static String createJWT(String id, String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间return builder.compact();}/*** 生成加密后的秘钥 secretKey* @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 解析** @param jwt* @return* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}
  2.  创建jwt过滤器
    @Component
    public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("token");if (!StringUtils.hasText(token)) {filterChain.doFilter(request, response);return;}String account = null;
    //校验tokentry {Claims claims = JwtUtil.parseJWT(token);account = claims.getSubject();} catch (Exception e) {e.printStackTrace();throw new RuntimeException("非法token");}
    //判断redis该用户是否超时存在if(Boolean.FALSE.equals(redisTemplate.boundHashOps(account).hasKey(account))){throw new RuntimeException("用户登录超时请重新登录");}
    //取出该用户相关信息 同时延长redis存储时间String redisUserObj = redisTemplate.boundHashOps(account).get(account).toString();redisTemplate.boundHashOps(account).expire(100000, TimeUnit.MILLISECONDS);UserBean userBean = JSON.parseObject(redisUserObj, UserBean.class);
    //将用户信息,及权限交给securityUsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userBean,null,userBean.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);filterChain.doFilter(request, response);}
    }
  3.  继承security适配器,配置security
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;//密码校验规则@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/login").anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();//把token校验过滤器添加到过滤器链中http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/login/**","/logout/**");}
    }
  4.  实现接口UserDetailsService 并实现方法,走我们自己的业务逻辑
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserBeanMapper userBeanMapper;@Overridepublic UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {return userBeanMapper.findUserById(account);}
    }

启动项目

  1. 启动类
    @SpringBootApplication
    public class SecurityApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SecurityApplication.class, args);BCryptPasswordEncoder bean = run.getBean(BCryptPasswordEncoder.class);System.out.println(bean.encode("123456"));}
    }
  2.  测试数据
  3.  admin登录
  4.  admin访问对应权限方法
  5.  zhangsan登录 
  6. zhangsan访问权限方法 

 写的不怎么样,希望对大家有用,希望大家多多指点~~~

springboot

一个简单的security安全登录示例

  1. 配置环境
    1. 添加pom依赖坐标
      <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version></parent><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency></dependencies>
    2.  application.yml文件配置
      server:port: 9999
      spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: rootmain:allow-bean-definition-overriding: trueredis:port: 6379host: 127.0.0.1
      logging:level:root: INFOorg.springframework.web.servlet.DispatcherServlet: DEBUGorg.springframework.cloud.sleuth: DEBUG
    3.  数据库就一张用户表(简单登录:用户表)
      SET NAMES utf8mb4;
      SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
      -- Table structure for tb_user
      -- ----------------------------
      DROP TABLE IF EXISTS `tb_user`;
      CREATE TABLE `tb_user`  (`id` int(11) NOT NULL,`account` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`role` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
      ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
      -- Records of tb_user
      -- ----------------------------
      INSERT INTO `tb_user` VALUES (1, '123456', 'admin', '$2a$10$gGKeupjLdvbaoYdAlz1MfuiT/4llYvGFU2QeQ..CQIhCXyqXekn5.', 'test');
      INSERT INTO `tb_user` VALUES (2, '789456', 'zhangsan', '$2a$10$gGKeupjLdvbaoYdAlz1MfuiT/4llYvGFU2QeQ..CQIhCXyqXekn5.', NULL);SET FOREIGN_KEY_CHECKS = 1;
    4. 编写统一返回类
      @Data
      @Accessors(chain = true)
      public class R {//成功状态位private Boolean success;//响应消息private String message;//响应码private Integer code;//响应数据private Object data;private static final String DEFAULT_SUCCESS_MESSAGE = "OK";private static final Integer DEFAULT_SUCCESS_CODE = 20000;private static final String DEFAULT_FALL_MESSAGE = "ERROR";private static final Integer DEFAULT_FALL_CODE = 50000;private R(Boolean success, String message, Integer code, Object data) {this.success = success;this.message = message;this.code = code;this.data = data;}public static R success(){R r = new R(true,DEFAULT_SUCCESS_MESSAGE,DEFAULT_SUCCESS_CODE,null);return r;}public static R success(String message){R r = new R(true,message,DEFAULT_SUCCESS_CODE,null);return r;}public static R success(Object data){R r = new R(true,DEFAULT_SUCCESS_MESSAGE,DEFAULT_SUCCESS_CODE,data);return r;}public static R success(String message,Object data){R r = new R(true,message,DEFAULT_SUCCESS_CODE,data);return r;}public static R fail(){R r = new R(false,DEFAULT_FALL_MESSAGE,DEFAULT_FALL_CODE,null);return r;}public static R fail(String message){R r = new R(false,message,DEFAULT_FALL_CODE,null);return r;}public static R fail(String message,Integer code){R r = new R(false,message,code,null);return r;}
      }
    5.  redis配置
      @Configuration
      public class RedisConfig {/*** retemplate相关配置* @param factory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();// 配置连接工厂template.setConnectionFactory(factory);//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);// 值采用json序列化template.setValueSerializer(jacksonSeial);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());// 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}}
  2.  创建实体类,实现接口UserDetails,实现获取权限方法
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true)
    public class UserBean implements UserDetails {private String account;private String username;private String password;private String role;@JSONField(serialize = false)private List<SimpleGrantedAuthority> authorities;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {if (authorities != null) {return authorities;}authorities = new ArrayList<>();if(null!=role){SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role);authorities.add(simpleGrantedAuthority);}return authorities;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
    }

  3.  创建mapper接口,编写sql语句
    @Mapper
    public interface UserBeanMapper {//根据账号查询用户信息@Select("select * from tb_user where account=#{account}")UserBean findUserById(@Param("account")String account);
    }
  4.  创建service层登录接口
    public interface UserBeanService {R login(String account,String password);
    }
  5.  实现service层接口
    @Service
    public class UserServiceImpl implements UserBeanService {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Overridepublic R login(String account, String password) {
    //创建用户身份验证UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(account, password);Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);if(null==authenticate){return R.fail("账户名或密码错误");}
    //以hash方式存储redis中redisTemplate.boundHashOps(account).put(account, JSON.toJSONString(authenticate.getPrincipal()));
    //设置redis过期时间redisTemplate.boundHashOps(account).expire(100000, TimeUnit.MILLISECONDS);return R.success(JwtUtil.createJWT(account));}
    }
  6.  创建controller层
    @RestController
    public class UserBeanController {@Autowiredprivate UserBeanService userBeanService;//登录@PostMapping("/login")public R login(@RequestParam("account") String account, @RequestParam("password") String password){return userBeanService.login(account,password);}//权限测试@GetMapping("/test")@PreAuthorize("hasAuthority('test')")public R test(){return R.success("这是一条提示消息","test");}
    }

 security相关代码配置

  1. 这里使用jwt令牌,创建jwt工具类
    /*** JWT工具类*/
    public class JwtUtil {//有效期为public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000  一个小时//设置秘钥明文public static final String JWT_KEY = "mingwen";public static String getUUID(){String token = UUID.randomUUID().toString().replaceAll("-", "");return token;}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @return*/public static String createJWT(String subject) {JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间return builder.compact();}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @param ttlMillis token超时时间* @return*/public static String createJWT(String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间return builder.compact();}private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);return Jwts.builder().setId(uuid)              //唯一的ID.setSubject(subject)   // 主题  可以是JSON数据.setIssuer("sanyue")     // 签发者.setIssuedAt(now)      // 签发时间.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥.setExpiration(expDate);}/*** 创建token* @param id* @param subject* @param ttlMillis* @return*/public static String createJWT(String id, String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间return builder.compact();}/*** 生成加密后的秘钥 secretKey* @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 解析** @param jwt* @return* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}
  2.  创建jwt过滤器
    @Component
    public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("token");if (!StringUtils.hasText(token)) {filterChain.doFilter(request, response);return;}String account = null;
    //校验tokentry {Claims claims = JwtUtil.parseJWT(token);account = claims.getSubject();} catch (Exception e) {e.printStackTrace();throw new RuntimeException("非法token");}
    //判断redis该用户是否超时存在if(Boolean.FALSE.equals(redisTemplate.boundHashOps(account).hasKey(account))){throw new RuntimeException("用户登录超时请重新登录");}
    //取出该用户相关信息 同时延长redis存储时间String redisUserObj = redisTemplate.boundHashOps(account).get(account).toString();redisTemplate.boundHashOps(account).expire(100000, TimeUnit.MILLISECONDS);UserBean userBean = JSON.parseObject(redisUserObj, UserBean.class);
    //将用户信息,及权限交给securityUsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userBean,null,userBean.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);filterChain.doFilter(request, response);}
    }
  3.  继承security适配器,配置security
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;//密码校验规则@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/login").anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();//把token校验过滤器添加到过滤器链中http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/login/**","/logout/**");}
    }
  4.  实现接口UserDetailsService 并实现方法,走我们自己的业务逻辑
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserBeanMapper userBeanMapper;@Overridepublic UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {return userBeanMapper.findUserById(account);}
    }

启动项目

  1. 启动类
    @SpringBootApplication
    public class SecurityApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SecurityApplication.class, args);BCryptPasswordEncoder bean = run.getBean(BCryptPasswordEncoder.class);System.out.println(bean.encode("123456"));}
    }
  2.  测试数据
  3.  admin登录
  4.  admin访问对应权限方法
  5.  zhangsan登录 
  6. zhangsan访问权限方法 

 写的不怎么样,希望对大家有用,希望大家多多指点~~~

发布评论

评论列表 (0)

  1. 暂无评论