赞
踩
目录
在网上找了很多基于spring cloud的security权限认证,但是大概都是网关内嵌security、security OAuth2的方式。这里给大家推荐另一种方式。以我的实战项目为例。
这里父工程为pzhxy,大家可以自己定义,Security为子工程。
(1)依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.data</groupId>
- <artifactId>spring-data-redis</artifactId>
- </dependency>
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt-api</artifactId>
- <version>0.10.7</version>
- <scope>compile</scope>
- </dependency>
(2)SecurityConfig
- package com.pzhxy.security.config;
-
-
- import com.pzhxy.security.filter.JwtAuthenticationTokenFilter;
- import com.pzhxy.security.handler.AccessDeniedHandlerImpl;
- import com.pzhxy.security.handler.AuthenticationEntryPointImpl;
- import com.pzhxy.security.passwordencode.MyPasswordEncoder;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.security.authentication.AuthenticationManager;
- import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
- import org.springframework.security.config.annotation.web.builders.HttpSecurity;
- import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
- import org.springframework.security.config.http.SessionCreationPolicy;
- import org.springframework.security.crypto.password.PasswordEncoder;
- import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
- import org.springframework.security.web.firewall.HttpFirewall;
- import org.springframework.security.web.firewall.StrictHttpFirewall;
-
- import javax.annotation.Resource;
-
-
- @Configuration
- @EnableGlobalMethodSecurity(prePostEnabled = true)
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- @Resource
- private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
- @Resource
- private AuthenticationEntryPointImpl authenticationEntryPoint;
- @Resource
- private AccessDeniedHandlerImpl accessDeniedHandler;
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.csrf().disable()
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- .authorizeRequests()
- .antMatchers(
- "/",
- "/swagger-ui.html",
- "/user/login",
- "/user/hello",
- "/operate/**",
- "/webjars/**",
- "/v2/**",
- "/link/**",
- "/process/**",
- "/proProcess/**",
- "/project/**",
- "/mail/**",
- "/qiniuyun/**",
- "/comments/getpage/**",
- "/swagger-resources/**").permitAll()
- .anyRequest().authenticated();
-
-
- http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
-
- //认证授权失败处理
- http.exceptionHandling()
- .authenticationEntryPoint(authenticationEntryPoint)
- .accessDeniedHandler(accessDeniedHandler);
- //允许跨域
- http.cors();
-
- }
-
- @Bean
- public PasswordEncoder passwordEncoder(){
- return new MyPasswordEncoder();
- }
-
-
- @Bean
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
- }
- }
(3)LoginUser
注:User类定义在feign中
- package com.pzhxy.security.domain;
-
- import com.baomidou.mybatisplus.annotation.TableField;
- import com.fasterxml.jackson.annotation.JsonIgnore;
- import com.pzhxy.feign.domain.User;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import org.springframework.security.core.userdetails.UserDetails;
-
- import java.util.Collection;
- import java.util.List;
- import java.util.stream.Collectors;
-
- /**
- * 登录用户身份权限
- *
- * @author ruoyi
- */
- public class LoginUser implements UserDetails
- {
- private static final long serialVersionUID = 1L;
-
- /**
- * 登录时间
- */
- private Long loginTime;
- /**
- * 权限列表
- */
- private List<String> permissions;
- /**
- * 用户信息
- */
- private User user;
-
-
- @JsonIgnore
- @TableField(exist = false)
- private List<SimpleGrantedAuthority>authorities;
-
- //获取权限信息
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities()
- {
- if(authorities!=null){
- return authorities;
- }
- //把permissios封装成对象
- authorities=permissions.stream()
- .map(SimpleGrantedAuthority::new)
- .collect(Collectors.toList());
- return authorities;
- }
-
- public LoginUser(){
-
- }
-
- public LoginUser(User user)
- {
- this.user = user;
- }
-
- @JsonIgnore
- @Override
- public String getPassword()
- {
- return user.getPassword();
- }
-
- @JsonIgnore
- @Override
- public String getUsername()
- {
- return user.getId();
- }
-
- /**
- * 账户是否未过期,过期无法验证
- */
- @JsonIgnore
- @Override
- public boolean isAccountNonExpired()
- {
- return true;
- }
-
- /**
- * 指定用户是否解锁,锁定的用户无法进行身份验证
- *
- * @return
- */
- @JsonIgnore
- @Override
- public boolean isAccountNonLocked()
- {
- return true;
- }
-
- /**
- * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
- *
- * @return
- */
- @JsonIgnore
- @Override
- public boolean isCredentialsNonExpired()
- {
- return true;
- }
-
- /**
- * 是否可用 ,禁用的用户不能身份验证
- *
- * @return
- */
- @JsonIgnore
- @Override
- public boolean isEnabled()
- {
- return true;
- }
-
- public Long getLoginTime()
- {
- return loginTime;
- }
-
- public void setLoginTime(Long loginTime)
- {
- this.loginTime = loginTime;
- }
-
- public List<String> getPermissions()
- {
- return permissions;
- }
-
- public void setPermissions(List<String> permissions)
- {
- this.permissions = permissions;
- }
-
- public User getUser()
- {
- return user;
- }
-
- public void setUser(User user)
- {
- this.user = user;
- }
-
-
- }
(4)JwtAuthenticationTokenFilter
- package com.pzhxy.security.filter;
-
-
- import com.pzhxy.redis.utils.JwtUtil;
- import com.pzhxy.redis.utils.RedisUtil;
-
- import com.pzhxy.security.domain.LoginUser;
- import io.jsonwebtoken.Claims;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StringUtils;
- import org.springframework.web.filter.OncePerRequestFilter;
-
- import javax.servlet.FilterChain;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.util.Objects;
-
- @Component
- public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
- @Autowired
- private RedisUtil redisUtil;
-
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
- String token = request.getHeader("Authorization");
- if(!StringUtils.hasText(token)){
- filterChain.doFilter(request,response);
- return;
- }
- String userid;
- try {
- //JWT解析token,截取userID
- Claims claims= JwtUtil.getClaim(token);
- userid=claims.get("userId").toString();
- }catch (Exception e){
- e.printStackTrace();
- throw new RuntimeException("token非法");
- }
- String redisKey="login:"+userid;
- LoginUser loginUser =(LoginUser)redisUtil.get(redisKey);
- System.out.println(loginUser);
- if(Objects.isNull(loginUser)){
- throw new RuntimeException("用户未登录");
- }
-
-
- //存入SecurityContextHolder,获取权限信息
- UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=new UsernamePasswordAuthenticationToken(loginUser,null, loginUser.getAuthorities());
- SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
- filterChain.doFilter(request,response);
- }
- }
(5)AccessDeniedHandlerImpl
- package com.pzhxy.security.handler;
-
- import com.alibaba.fastjson.JSON;
- import com.pzhxy.constant.result.ResultBean;
- import org.springframework.http.HttpStatus;
- import org.springframework.security.access.AccessDeniedException;
- import org.springframework.security.web.access.AccessDeniedHandler;
- import org.springframework.stereotype.Component;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /***
- * 授权失败处理
- *@Date:2022/6/4
- * @Author: Liu
- */
- @Component
- public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
- @Override
- public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
- ResultBean result=new ResultBean(HttpStatus.FORBIDDEN.value(),"您的权限不足");
- String json= JSON.toJSONString(result);
- response.setStatus(200);
- response.setContentType("application/json");
- response.setCharacterEncoding("utf-8");
- response.getWriter().print(json);
- }
- }
(6)AuthenticationEntryPointImpl
- package com.pzhxy.security.handler;
-
- import com.alibaba.fastjson.JSON;
- import com.pzhxy.constant.result.ResultBean;
- import org.springframework.http.HttpStatus;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.AuthenticationEntryPoint;
- import org.springframework.stereotype.Component;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /**
- * 认证失败处理
- *@Date:2022/6/4
- * @Author: Liu
- */
- @Component
- public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
- @Override
- public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
- ResultBean result=new ResultBean(HttpStatus.UNAUTHORIZED.value(),"用户认证失败请查询登录");
- String json= JSON.toJSONString(result);
- response.setStatus(200);
- response.setContentType("application/json");
- response.setCharacterEncoding("utf-8");
- response.getWriter().print(json);
- }
-
- }
(7)MyPasswordEncoder(自定义加密方式)
- package com.pzhxy.security.passwordencode;
-
- import com.pzhxy.security.utils.MD5Util;
- import org.springframework.security.crypto.password.PasswordEncoder;
-
-
- import java.util.Objects;
-
- public class MyPasswordEncoder implements PasswordEncoder {
- @Override
- public String encode(CharSequence charSequence) {
- return MD5Util.encode((String) charSequence);
- }
-
- //加密验证方法
- @Override
- public boolean matches(CharSequence rawPassword, String encodedPassword) {
- return Objects.equals(rawPassword, encodedPassword);
- }
- }
-
-
(8)MD5Util(MD5加密方式)
- package com.pzhxy.security.utils;
- import java.security.MessageDigest;
- /**
- * @author 言曌
- * @date 2018/2/9 下午6:11
- */
- public class MD5Util {
- private static final String SALT = "liuyanzhao.com";
- /**
- * MD5加盐加密
- *
- * @param password
- * @return
- */
- public static String encode(String password) {
- password = password + SALT;
- MessageDigest md5 = null;
- try {
- md5 = MessageDigest.getInstance("MD5");
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- char[] charArray = password.toCharArray();
- byte[] byteArray = new byte[charArray.length];
- for (int i = 0; i < charArray.length; i++)
- byteArray[i] = (byte) charArray[i];
- byte[] md5Bytes = md5.digest(byteArray);
- StringBuffer hexValue = new StringBuffer();
- for (int i = 0; i < md5Bytes.length; i++) {
- int val = ((int) md5Bytes[i]) & 0xff;
- if (val < 16) {
- hexValue.append("0");
- }
- hexValue.append(Integer.toHexString(val));
- }
- return hexValue.toString();
- }
-
- public static void main(String[] args) {
- String hashPass = MD5Util.encode("123456");
- System.out.println(MD5Util.encode("123456"));//08dc78d36d1512e5a81ef05b01a37860
- System.out.println("08dc78d36d1512e5a81ef05b01a37860".equals(hashPass));//true
- }
- }
(1)common-utils结构
(2)搭建feign
这里只需要自定义的User类,大家按自己需求写。
依赖
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
- <dependency>
- <groupId>org.example</groupId>
- <artifactId>common-base</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>compile</scope>
- </dependency>
-
- </dependencies>
(3)搭建common-base
这里只需要ResultBean封装结果,大家可以自己定义
- package com.pzhxy.constant.result;
-
- import lombok.Data;
-
- import java.util.HashMap;
- import java.util.Map;
-
- /***
- * 返回结果的统一封装
- */
-
- @Data
- public class ResultBean<T> {
-
- private Boolean success; //是否成功
-
- private Integer code; //返回状态码
-
- private String message; //返回消息提示
-
- private T data;
-
- private ResultBean(){}
-
- public static ResultBean ok(){
- ResultBean r = new ResultBean();
- r.setSuccess(true);
- r.setCode(ResultCode.SUCCESS);
- r.setMessage("成功");
- return r;
- }
-
- public static ResultBean error(){
- ResultBean r = new ResultBean();
- r.setSuccess(false);
- r.setCode(ResultCode.ERROR);
- r.setMessage("失败");
- return r;
- }
-
- public ResultBean(Integer code, String message) {
- this.code = code;
- this.message = message;
- }
-
- public ResultBean success(Boolean success){
- this.setSuccess(success);
- return this;
- }
-
- public ResultBean message(String message){
- this.setMessage(message);
- return this;
- }
-
- public ResultBean code(Integer code){
- this.setCode(code);
- return this;
- }
-
- public ResultBean(Integer code, String message, T data) {
- this.code = code;
- this.message = message;
- this.data = data;
- }
- }
-
-
依赖
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-autoconfigure</artifactId>
- </dependency>
(4)搭建redis
- <dependencies>
- <!-- redis-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.datatype</groupId>
- <artifactId>jackson-datatype-jsr310</artifactId>
- </dependency>
- <!-- JWT-->
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt-api</artifactId>
- <version>0.10.7</version>
- </dependency>
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt-impl</artifactId>
- <version>0.10.7</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt-jackson</artifactId>
- <version>0.10.7</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-pool2</artifactId>
- <version>2.2</version>
- </dependency>
- </dependencies>
- package com.pzhxy.redis.config;
-
-
- import com.fasterxml.jackson.annotation.JsonAutoDetect;
- import com.fasterxml.jackson.annotation.PropertyAccessor;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.connection.RedisConnectionFactory;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
- import org.springframework.data.redis.serializer.StringRedisSerializer;
-
- import java.net.UnknownHostException;
-
- @Configuration
- public class RedisConfig {
- //编写自己的redisTemplate
- @Bean
- @SuppressWarnings("all")
- public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
- // 为了开发方便,直接使用<String, Object>
- RedisTemplate<String, Object> template = new RedisTemplate();
- template.setConnectionFactory(redisConnectionFactory);
-
- // Json 配置序列化
- // 使用 jackson 解析任意的对象
- Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
- // 使用 objectMapper 进行转义
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
- // String 的序列化
- StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
-
- // key 采用 String 的序列化方式
- template.setKeySerializer(stringRedisSerializer);
- // Hash 的 key 采用 String 的序列化方式
- template.setHashKeySerializer(stringRedisSerializer);
- // value 采用 jackson 的序列化方式
- template.setValueSerializer(jackson2JsonRedisSerializer);
- // Hash 的 value 采用 jackson 的序列化方式
- template.setHashValueSerializer(jackson2JsonRedisSerializer);
- // 把所有的配置 set 进 template
- template.afterPropertiesSet();
-
- return template;
- }
- }
-
-
-
- package com.pzhxy.redis.utils;
-
- import io.jsonwebtoken.*;
- import io.jsonwebtoken.security.Keys;
-
- import javax.crypto.SecretKey;
- import java.text.SimpleDateFormat;
- import java.util.Base64;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * @author:Tlimited
- *
- */
- public class JwtUtil {
-
- private static final long EXPIRE = 60 * 1000 * 60 * 24; //过期时间
- //密钥,动态生成的密钥
- // public static final SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
- //固定秘钥,非动态
- public static String key = "LiuYangdejavawebtuanduidediyigexiangmujijiangwancheng";
-
- /**
- * 生成token
- *
- * @param claims 要传送消息map
- * @return
- */
- public static String generate(Map<String,Object> claims) {
- Date nowDate = new Date();
- //过期时间,设定为一分钟
- Date expireDate = new Date(System.currentTimeMillis() + EXPIRE);
- //头部信息,可有可无
- Map<String, Object> header = new HashMap<>(2);
- header.put("typ", "jwt");
-
- //更强的密钥,JDK11起才能用
- // KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);
- // PrivateKey key1 = keyPair.getPrivate(); // 私钥
- //PublicKey key2 = keyPair.getPublic(); //公钥
-
- return Jwts.builder().setHeader(header)
- // .setSubject("weimi")//主题
- // .setIssuer("weimi") //发送方
- .setClaims(claims) //自定义claims
- .setIssuedAt(nowDate)//当前时间
- .setExpiration(expireDate) //过期时间
- .signWith(SignatureAlgorithm.HS256,key)//签名算法和key
- .compact();
- }
-
- /**
- * 生成token
- * @param header 传入头部信息map
- * @param claims 要传送消息map
- * @return
- */
- public static String generate( Map<String, Object> header,Map<String,Object> claims) {
- Date nowDate = new Date();
- //过期时间,设定为一分钟
- Date expireDate = new Date(System.currentTimeMillis() + EXPIRE);
-
- return Jwts.builder().setHeader(header)
- // .setSubject("weimi")//主题
- // .setIssuer("weimi") //发送方
- .setClaims(claims) //自定义claims
- .setIssuedAt(nowDate)//当前时间
- .setExpiration(expireDate) //过期时间
- .signWith(SignatureAlgorithm.HS256,key)//签名算法和key
- .compact();
- }
-
- /**
- * 校验是不是jwt签名
- * @param token
- * @return
- */
- public static boolean isSigned(String token){
- return Jwts.parser()
- .setSigningKey(key)
- .isSigned(token);
- }
-
- /**
- * 校验签名是否正确
- * @param token
- * @return
- */
- public static boolean verify(String token){
- try {
- Jwts.parser()
- .setSigningKey(key)
- .parseClaimsJws(token);
- return true;
- }catch (JwtException e){
- System.out.println(e.getMessage());
- return false;
- }
- }
-
- /**
- * 获取payload 部分内容(即要传的信息)
- * 使用方法:如获取userId:getClaim(token).get("userId");
- * @param token
- * @return
- */
- public static Claims getClaim(String token) {
- Claims claims = null;
- try {
- claims = Jwts.parser()
- .setSigningKey(key)
- .parseClaimsJws(token)
- .getBody();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return claims;
- }
-
- /**
- * 获取头部信息map
- * 使用方法 : getHeader(token).get("alg");
- * @param token
- * @return
- */
- public static JwsHeader getHeader(String token) {
- JwsHeader header = null;
- try {
- header = Jwts.parser()
- .setSigningKey(key)
- .parseClaimsJws(token)
- .getHeader();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return header;
- }
-
- /**
- * 获取jwt发布时间
- */
- public static Date getIssuedAt(String token) {
- return getClaim(token).getIssuedAt();
- }
-
- /**
- * 获取jwt失效时间
- */
- public static Date getExpiration(String token) {
- return getClaim(token).getExpiration();
- }
-
- /**
- * 验证token是否失效
- *
- * @param token
- * @return true:过期 false:没过期
- */
- public static boolean isExpired(String token) {
- try {
- final Date expiration = getExpiration(token);
- return expiration.before(new Date());
- } catch (ExpiredJwtException expiredJwtException) {
- return true;
- }
- }
-
- /**
- * 直接Base64解密获取header内容
- * @param token
- * @return
- */
- public static String getHeaderByBase64(String token){
- String header = null;
- if (isSigned(token)){
- try {
- byte[] header_byte = Base64.getDecoder().decode(token.split("\\.")[0]);
- header = new String(header_byte);
- }catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
- return header;
- }
-
- /**
- * 直接Base64解密获取payload内容
- * @param token
- * @return
- */
- public static String getPayloadByBase64(String token){
- String payload = null;
- if (isSigned(token)) {
- try {
- byte[] payload_byte = Base64.getDecoder().decode(token.split("\\.")[1]);
- payload = new String(payload_byte);
- }catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
- return payload;
- }
-
- public static void main(String[] args) {
- //用户自定义信息claims
- Map<String,Object> map = new HashMap<>();
- map.put("userId","admin");
- String token = generate(map);
- System.out.println(token);
-
- System.out.println("claim:" + getClaim(token).get("userId"));
- System.out.println("header:" + getHeader(token));
- // System.out.println(getIssuedAt(token));
- Claims claims=getClaim(token);
-
- // System.out.println(getHeaderByBase64(token));
- System.out.println(getPayloadByBase64(token));
-
- SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
- System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
- System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
- System.out.println("当前时间:"+sdf.format(new Date()) );
-
- }
- }
-
- package com.pzhxy.redis.utils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Component;
- import org.springframework.util.CollectionUtils;
-
- import javax.annotation.Resource;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.TimeUnit;
- /**
- * @author Zly
- * @date 2019/8/7 0007 17:30
- */
- @Component
- public class RedisUtil {
- @Resource
- private RedisTemplate<String, Object> redisTemplate;
- // =============================common============================
- /**
- * 指定缓存失效时间
- * @param key 键
- * @param time 时间(秒)
- * @return
- */
- public boolean expire(String key, long time) {
- try {
- if (time > 0) {
- redisTemplate.expire(key, time, TimeUnit.SECONDS);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 根据key 获取过期时间
- * @param key 键 不能为null
- * @return 时间(秒) 返回0代表为永久有效
- */
- public long getExpire(String key) {
- return redisTemplate.getExpire(key, TimeUnit.SECONDS);
- }
- /**
- * 判断key是否存在
- * @param key 键
- * @return true 存在 false不存在
- */
- public boolean hasKey(String key) {
- try {
- return redisTemplate.hasKey(key);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 删除缓存
- * @param key 可以传一个值 或多个
- */
- @SuppressWarnings("unchecked")
- public void del(String... key) {
- if (key != null && key.length > 0) {
- if (key.length == 1) {
- redisTemplate.delete(key[0]);
- } else {
- redisTemplate.delete(CollectionUtils.arrayToList(key));
- }
- }
- }
- // ============================String=============================
- /**
- * 普通缓存获取
- * @param key 键
- * @return 值
- */
- public Object get(String key) {
- return key == null ? null : redisTemplate.opsForValue().get(key);
- }
- /**
- * 普通缓存放入
- * @param key 键
- * @param value 值
- * @return true成功 false失败
- */
- public boolean set(String key, Object value) {
- try {
- redisTemplate.opsForValue().set(key, value);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 普通缓存放入并设置时间
- * @param key 键
- * @param value 值
- * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
- * @return true成功 false 失败
- */
- public boolean set(String key, Object value, long time) {
- try {
- if (time > 0) {
- redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
- } else {
- set(key, value);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 递增
- * @param key 键
- * @param delta 要增加几(大于0)
- * @return
- */
- public long incr(String key, long delta) {
- if (delta < 0) {
- throw new RuntimeException("递增因子必须大于0");
- }
- return redisTemplate.opsForValue().increment(key, delta);
- }
- /**
- * 递减
- * @param key 键
- * @param delta 要减少几(小于0)
- * @return
- */
- public long decr(String key, long delta) {
- if (delta < 0) {
- throw new RuntimeException("递减因子必须大于0");
- }
- return redisTemplate.opsForValue().increment(key, -delta);
- }
- // ================================Map=================================
- /**
- * HashGet
- * @param key 键 不能为null
- * @param item 项 不能为null
- * @return 值
- */
- public Object hget(String key, String item) {
- return redisTemplate.opsForHash().get(key, item);
- }
- /**
- * 获取hashKey对应的所有键值
- * @param key 键
- * @return 对应的多个键值
- */
- public Map<Object, Object> hmget(String key) {
- return redisTemplate.opsForHash().entries(key);
- }
- /**
- * HashSet
- * @param key 键
- * @param map 对应多个键值
- * @return true 成功 false 失败
- */
- public boolean hmset(String key, Map<String, Object> map) {
- try {
- redisTemplate.opsForHash().putAll(key, map);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * HashSet 并设置时间
- * @param key 键
- * @param map 对应多个键值
- * @param time 时间(秒)
- * @return true成功 false失败
- */
- public boolean hmset(String key, Map<String, Object> map, long time) {
- try {
- redisTemplate.opsForHash().putAll(key, map);
- if (time > 0) {
- expire(key, time);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 向一张hash表中放入数据,如果不存在将创建
- * @param key 键
- * @param item 项
- * @param value 值
- * @return true 成功 false失败
- */
- public boolean hset(String key, String item, Object value) {
- try {
- redisTemplate.opsForHash().put(key, item, value);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 向一张hash表中放入数据,如果不存在将创建
- * @param key 键
- * @param item 项
- * @param value 值
- * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
- * @return true 成功 false失败
- */
- public boolean hset(String key, String item, Object value, long time) {
- try {
- redisTemplate.opsForHash().put(key, item, value);
- if (time > 0) {
- expire(key, time);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 删除hash表中的值
- * @param key 键 不能为null
- * @param item 项 可以使多个 不能为null
- */
- public void hdel(String key, Object... item) {
- redisTemplate.opsForHash().delete(key, item);
- }
- /**
- * 判断hash表中是否有该项的值
- * @param key 键 不能为null
- * @param item 项 不能为null
- * @return true 存在 false不存在
- */
- public boolean hHasKey(String key, String item) {
- return redisTemplate.opsForHash().hasKey(key, item);
- }
- /**
- * hash递增 如果不存在,就会创建一个 并把新增后的值返回
- * @param key 键
- * @param item 项
- * @param by 要增加几(大于0)
- * @return
- */
- public double hincr(String key, String item, double by) {
- return redisTemplate.opsForHash().increment(key, item, by);
- }
- /**
- * hash递减
- * @param key 键
- * @param item 项
- * @param by 要减少记(小于0)
- * @return
- */
- public double hdecr(String key, String item, double by) {
- return redisTemplate.opsForHash().increment(key, item, -by);
- }
- // ============================set=============================
- /**
- * 根据key获取Set中的所有值
- * @param key 键
- * @return
- */
- public Set<Object> sGet(String key) {
- try {
- return redisTemplate.opsForSet().members(key);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 根据value从一个set中查询,是否存在
- * @param key 键
- * @param value 值
- * @return true 存在 false不存在
- */
- public boolean sHasKey(String key, Object value) {
- try {
- return redisTemplate.opsForSet().isMember(key, value);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 将数据放入set缓存
- * @param key 键
- * @param values 值 可以是多个
- * @return 成功个数
- */
- public long sSet(String key, Object... values) {
- try {
- return redisTemplate.opsForSet().add(key, values);
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- /**
- * 将set数据放入缓存
- * @param key 键
- * @param time 时间(秒)
- * @param values 值 可以是多个
- * @return 成功个数
- */
- public long sSetAndTime(String key, long time, Object... values) {
- try {
- Long count = redisTemplate.opsForSet().add(key, values);
- if (time > 0) {
- expire(key, time);
- }
- return count;
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- /**
- * 获取set缓存的长度
- * @param key 键
- * @return
- */
- public long sGetSetSize(String key) {
- try {
- return redisTemplate.opsForSet().size(key);
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- /**
- * 移除值为value的
- * @param key 键
- * @param values 值 可以是多个
- * @return 移除的个数
- */
- public long setRemove(String key, Object... values) {
- try {
- Long count = redisTemplate.opsForSet().remove(key, values);
- return count;
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- // ===============================list=================================
- /**
- * 获取list缓存的内容
- * @param key 键
- * @param start 开始
- * @param end 结束 0 到 -1代表所有值
- * @return
- */
- public List<Object> lGet(String key, long start, long end) {
- try {
- return redisTemplate.opsForList().range(key, start, end);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 获取list缓存的长度
- * @param key 键
- * @return
- */
- public long lGetListSize(String key) {
- try {
- return redisTemplate.opsForList().size(key);
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- /**
- * 通过索引 获取list中的值
- * @param key 键
- * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
- * @return
- */
- public Object lGetIndex(String key, long index) {
- try {
- return redisTemplate.opsForList().index(key, index);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 将list放入缓存
- * @param key 键
- * @param value 值
- * @return
- */
- public boolean lSet(String key, Object value) {
- try {
- redisTemplate.opsForList().rightPush(key, value);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 将list放入缓存
- * @param key 键
- * @param value 值
- * @param time 时间(秒)
- * @return
- */
- public boolean lSet(String key, Object value, long time) {
- try {
- redisTemplate.opsForList().rightPush(key, value);
- if (time > 0) {
- expire(key, time);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 将list放入缓存
- * @param key 键
- * @param value 值
- * @return
- */
- public boolean lSet(String key, List<Object> value) {
- try {
- redisTemplate.opsForList().rightPushAll(key, value);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 将list放入缓存
- *
- * @param key 键
- * @param value 值
- * @param time 时间(秒)
- * @return
- */
- public boolean lSet(String key, List<Object> value, long time) {
- try {
- redisTemplate.opsForList().rightPushAll(key, value);
- if (time > 0) {
- expire(key, time);
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 根据索引修改list中的某条数据
- * @param key 键
- * @param index 索引
- * @param value 值
- * @return
- */
- public boolean lUpdateIndex(String key, long index, Object value) {
- try {
- redisTemplate.opsForList().set(key, index, value);
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
- /**
- * 移除N个值为value
- * @param key 键
- * @param count 移除多少个
- * @param value 值
- * @return 移除的个数
- */
- public long lRemove(String key, long count, Object value) {
- try {
- Long remove = redisTemplate.opsForList().remove(key, count, value);
- return remove;
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
- }
UserDetails
- package com.pzhxy.user.service.impl;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
-
- import com.pzhxy.feign.domain.User;
- import com.pzhxy.security.domain.LoginUser;
- import com.pzhxy.user.mapper.PermissionMapper;
- import com.pzhxy.user.mapper.UserMapper;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.core.userdetails.UserDetailsService;
- import org.springframework.security.core.userdetails.UsernameNotFoundException;
- import org.springframework.stereotype.Service;
-
- import java.util.List;
- import java.util.Objects;
-
- @Service("userDetailsService")
- public class UserDetalisServiceImpl implements UserDetailsService {
- /***
- * 进行认证,认证是从数据库查询账号密码
- *@Date:2022/5/22
- * @Author: Liu
- */
- @Autowired
- private UserMapper userMapper;
- @Autowired
- private PermissionMapper permissionMapper;
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- //调用usermapper,实现数据库查询
- QueryWrapper<User>wrapper=new QueryWrapper<>();
- wrapper.eq("id",username);
- User user = userMapper.selectOne(wrapper);
- if(Objects.isNull(user)){
- //数据库无该用户,认证失败
- throw new RuntimeException("用户名不存在");
- }
- //授权
- List<String> list = permissionMapper.selectPermsByUserId(user.getId());
-
- LoginUser loginUser=new LoginUser();
- loginUser.setUser(user);
- loginUser.setPermissions(list);
- return loginUser;
- }
- }
- package com.pzhxy.user.controller;
-
- import com.pzhxy.constant.result.ResultBean;
- import com.pzhxy.feign.domain.User;
-
-
- import com.pzhxy.user.service.impl.LoginServiceImpl;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
-
- @RestController
- @RequestMapping("/user")
- public class LoginController {
- @Autowired
- private LoginServiceImpl loginService;
-
-
- @PostMapping("/login")
- public ResultBean login(@RequestBody User user){
- return loginService.login(user);
- }
-
- @GetMapping("/logout")
- public ResultBean loginout(){
- return loginService.logout();
- }
- }
在其他微服务中导入你的security服务的依赖即可
例如user-servcie
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。