目录
Spring Cloud Gateway是基于,和。结果,当您使用Spring Cloud Gateway时,定制设计许多您熟悉的同步库(例如,Spring Data和Spring Security)定制设计和模式可能不适用。定制设计如果您不熟悉这些项目,定制设计建议您在使用Spring Cloud Gateway定制设计之前先阅读它们的文档定制设计以熟悉一些新概念。
Spring-Security
Spring Security定制设计是一个提供身份验证,定制设计授权和保护以防止常见定制设计攻击的框架。定制设计凭借对命令式和响应式定制设计应用程序的一流支持,定制设计它是用于保护基于Spring定制设计的应用程序的事实上的标准。
Spring-Webflux
Spring定制设计框架中包含的原始Web框架Spring Web MVC是专门为Servlet API和Servlet定制设计容器而构建的。定制设计响应式堆栈Web框架Spring WebFlux在稍后的5.0版中添加。定制设计它是完全无阻塞的,支持 背压,并在Netty,Undertow和Servlet 3.1+容器等服务器上运行。
这两个Web框架都反映了其源模块的名称(和 ),并在Spring Framework中并存。每个模块都是可选的。应用程序可以使用一个模块,也可以使用两个模块,在某些情况下,也可以使用两个模块,例如,带有的Spring MVC控制器WebClient
。
注意
由于Web容器不同,在Gateway项目中使用的WebFlux,是不能和Spring-Web混合使用的。 Spring MVC和 WebFlux 的区别:
编码
项目环境版本
- Spring-Cloud:2020.0.1
- Spring-Boot: 2.4.3
gradle 依赖
- dependencies {
- implementation(
- 'org.springframework.cloud:spring-cloud-starter-gateway',
- 'org.springframework.boot:spring-boot-starter-security'
- )
- }
- 复制代码
Spring-Security配置
spring security设置要采用响应式配置,基于WebFlux中WebFilter实现,与Spring MVC的Security是通过Servlet的Filter实现类似,也是一系列filter组成的过滤链。
Reactor与传统MVC配置对应:
webflux | mvc | 作用 |
---|---|---|
@EnableWebFluxSecurity | @EnableWebSecurity | 开启security配置 |
ServerAuthenticationSuccessHandler | AuthenticationSuccessHandler | 登录成功Handler |
ServerAuthenticationFailureHandler | AuthenticationFailureHandler | 登陆失败Handler |
ReactiveAuthorizationManager | AuthorizationManager | 认证管理 |
ServerSecurityContextRepository | SecurityContextHolder | 认证信息存储管理 |
ReactiveUserDetailsService | UserDetailsService | 用户登录 |
ReactiveAuthorizationManager | AccessDecisionManager | 鉴权管理 |
ServerAuthenticationEntryPoint | AuthenticationEntryPoint | 未认证Handler |
ServerAccessDeniedHandler | AccessDeniedHandler | 鉴权失败Handler |
1. Security核心配置
- package com.pluto.gateway.security;
-
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.http.HttpMethod;
- import org.springframework.security.authentication.DelegatingReactiveAuthenticationManager;
- import org.springframework.security.authentication.ReactiveAuthenticationManager;
- import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
- import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
- import org.springframework.security.config.web.server.ServerHttpSecurity;
- import org.springframework.security.crypto.factory.PasswordEncoderFactories;
- import org.springframework.security.crypto.password.PasswordEncoder;
- import org.springframework.security.web.server.SecurityWebFilterChain;
- import reactor.core.publisher.Mono;
- import javax.annotation.Resource;
- import java.util.LinkedList;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 10:56
- * @description webflux security核心配置类
- */
- @EnableWebFluxSecurity
- public class WebfluxSecurityConfig {
- @Resource
- private DefaultAuthorizationManager defaultAuthorizationManager;
-
- @Resource
- private UserDetailsServiceImpl userDetailsServiceImpl;
-
- @Resource
- private DefaultAuthenticationSuccessHandler defaultAuthenticationSuccessHandler;
-
- @Resource
- private DefaultAuthenticationFailureHandler defaultAuthenticationFailureHandler;
-
- @Resource
- private TokenAuthenticationManager tokenAuthenticationManager;
-
- @Resource
- private DefaultSecurityContextRepository defaultSecurityContextRepository;
-
- @Resource
- private DefaultAuthenticationEntryPoint defaultAuthenticationEntryPoint;
-
- @Resource
- private DefaultAccessDeniedHandler defaultAccessDeniedHandler;
-
- /**
- * 自定义过滤权限
- */
- @Value("${security.noFilter}")
- private String noFilter;
-
- @Bean
- public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
- httpSecurity
- // 登录认证处理
- .authenticationManager(reactiveAuthenticationManager())
- .securityContextRepository(defaultSecurityContextRepository)
- // 请求拦截处理
- .authorizeExchange(exchange -> exchange
- .pathMatchers(noFilter).permitAll()
- .pathMatchers(HttpMethod.OPTIONS).permitAll()
- .anyExchange().access(defaultAuthorizationManager)
- )
- .formLogin()
- // 自定义处理
- .authenticationSuccessHandler(defaultAuthenticationSuccessHandler)
- .authenticationFailureHandler(defaultAuthenticationFailureHandler)
- .and()
- .exceptionHandling()
- .authenticationEntryPoint(defaultAuthenticationEntryPoint)
- .and()
- .exceptionHandling()
- .accessDeniedHandler(defaultAccessDeniedHandler)
- .and()
- .csrf().disable()
- ;
- return httpSecurity.build();
- }
-
- /**
- * BCrypt密码编码
- */
- @Bean("passwordEncoder")
- public PasswordEncoder passwordEncoder() {
- return PasswordEncoderFactories.createDelegatingPasswordEncoder();
- }
-
- /**
- * 注册用户信息验证管理器,可按需求添加多个按顺序执行
- */
- @Bean
- ReactiveAuthenticationManager reactiveAuthenticationManager() {
- LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
- managers.add(authentication -> {
- // 其他登陆方式 (比如手机号验证码登陆) 可在此设置不得抛出异常或者 Mono.error
- return Mono.empty();
- });
- // 必须放最后不然会优先使用用户名密码校验但是用户名密码不对时此 AuthenticationManager 会调用 Mono.error 造成后面的 AuthenticationManager 不生效
- managers.add(new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsServiceImpl));
- managers.add(tokenAuthenticationManager);
- return new DelegatingReactiveAuthenticationManager(managers);
- }
- }
- 复制代码
2.用户认证
- package com.pluto.gateway.security;
-
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.userdetails.User;
- import java.io.Serializable;
- import java.util.Collection;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/10 13:15
- * @description 自定义用户信息
- */
- public class SecurityUserDetails extends User implements Serializable {
-
- private Long userId;
-
- public SecurityUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities, Long userId) {
- super(username, password, authorities);
- this.userId = userId;
- }
-
- public SecurityUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities, Long userId) {
- super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
- this.userId = userId;
- }
-
- public Long getUserId() {
- return userId;
- }
-
- public void setUserId(Long userId) {
- this.userId = userId;
- }
- }
-
- 复制代码
- package com.pluto.gateway.security;
-
- import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
- import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.crypto.password.PasswordEncoder;
- import org.springframework.stereotype.Service;
- import reactor.core.publisher.Mono;
- import javax.annotation.Resource;
- import java.util.ArrayList;
-
- /**
- * @author ceshi
- * @date 2021/3/9 14:03
- * @description 用户登录处理
- * @version 1.0.0
- */@Service
- public class UserDetailsServiceImpl implements ReactiveUserDetailsService {
-
- @Resource
- private PasswordEncoder passwordEncoder;
-
- @Override
- public Mono<UserDetails> findByUsername(String username) {
- SecurityUserDetails securityUserDetails = new SecurityUserDetails(
- "user",
- passwordEncoder.encode("user"),
- true, true, true, true, new ArrayList<>(),
- 1L
- );
- return Mono.just(securityUserDetails);
- }
- }
- 复制代码
3.1 自定义登录成功
- package com.pluto.gateway.security;
-
- import com.alibaba.fastjson.JSONObject;
- import com.pluto.common.basic.utils.JwtTokenUtil;
- import com.pluto.common.basic.utils.ResultVoUtil;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferFactory;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.web.server.WebFilterExchange;
- import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
- import org.springframework.stereotype.Component;
- import reactor.core.publisher.Mono;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 15:00
- * @description 登录成功处理
- */
- @Component
- public class DefaultAuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler {
-
- /**
- * token 过期时间
- */
- @Value("${jwt.token.expired}")
- private int jwtTokenExpired;
-
- /**
- * 刷新token 时间
- */
- @Value("${jwt.token.refresh.expired}")
- private int jwtTokenRefreshExpired;
-
- @Override
- public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
- return Mono.defer(() -> Mono.just(webFilterExchange.getExchange().getResponse()).flatMap(response -> {
- DataBufferFactory dataBufferFactory = response.bufferFactory();
- // 生成JWT token
- Map<String, Object> map = new HashMap<>(2);
- SecurityUserDetails userDetails = (SecurityUserDetails) authentication.getPrincipal();
- map.put("userId", userDetails.getUserId());
- map.put("username", userDetails.getUsername());
- map.put("roles",userDetails.getAuthorities());
- String token = JwtTokenUtil.generateToken(map, userDetails.getUsername(), jwtTokenExpired);
- String refreshToken = JwtTokenUtil.generateToken(map, userDetails.getUsername(), jwtTokenRefreshExpired);
- Map<String, Object> tokenMap = new HashMap<>(2);
- tokenMap.put("token", token);
- tokenMap.put("refreshToken", refreshToken);
- DataBuffer dataBuffer = dataBufferFactory.wrap(JSONObject.toJSONString(ResultVoUtil.success(tokenMap)).getBytes());
- return response.writeWith(Mono.just(dataBuffer));
- }));
- }
- }
- 复制代码
3.2 自定义登录失败Handler
- package com.pluto.gateway.security;
-
- import com.alibaba.fastjson.JSONObject;
- import com.pluto.common.basic.enums.UserStatusCodeEnum;
- import com.pluto.common.basic.utils.ResultVoUtil;
- import com.pluto.common.basic.vo.ResultVO;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferFactory;
- import org.springframework.security.authentication.*;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.core.userdetails.UsernameNotFoundException;
- import org.springframework.security.web.server.WebFilterExchange;
- import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
- import org.springframework.stereotype.Component;
- import reactor.core.publisher.Mono;
- import java.util.Map;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 15:14
- * @description 登录失败处理
- */
- @Component
- public class DefaultAuthenticationFailureHandler implements ServerAuthenticationFailureHandler {
-
- @Override
- public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
- return Mono.defer(() -> Mono.just(webFilterExchange.getExchange()
- .getResponse()).flatMap(response -> {
- DataBufferFactory dataBufferFactory = response.bufferFactory();
- ResultVO<Map<String, Object>> resultVO = ResultVoUtil.error();
- // 账号不存在
- if (exception instanceof UsernameNotFoundException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_NOT_EXIST);
- // 用户名或密码错误
- } else if (exception instanceof BadCredentialsException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.LOGIN_PASSWORD_ERROR);
- // 账号已过期
- } else if (exception instanceof AccountExpiredException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_EXPIRED);
- // 账号已被锁定
- } else if (exception instanceof LockedException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_LOCKED);
- // 用户凭证已失效
- } else if (exception instanceof CredentialsExpiredException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_CREDENTIAL_EXPIRED);
- // 账号已被禁用
- } else if (exception instanceof DisabledException) {
- resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_DISABLE);
- }
- DataBuffer dataBuffer = dataBufferFactory.wrap(JSONObject.toJSONString(resultVO).getBytes());
- return response.writeWith(Mono.just(dataBuffer));
- }));
- }
- }
- 复制代码
3.3 自定义未认证Handler
- package com.pluto.gateway.security;
-
- import com.alibaba.fastjson.JSONObject;
- import com.pluto.common.basic.enums.UserStatusCodeEnum;
- import com.pluto.common.basic.utils.ResultVoUtil;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferFactory;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.MediaType;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
- import org.springframework.stereotype.Component;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
- import java.nio.charset.Charset;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 15:17
- * @description 未认证处理
- */
- @Component
- public class DefaultAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
-
- @Override
- public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
- return Mono.defer(() -> Mono.just(exchange.getResponse())).flatMap(response -> {
- response.setStatusCode(HttpStatus.UNAUTHORIZED);
- response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
- DataBufferFactory dataBufferFactory = response.bufferFactory();
- String result = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.USER_UNAUTHORIZED));
- DataBuffer buffer = dataBufferFactory.wrap(result.getBytes(
- Charset.defaultCharset()));
- return response.writeWith(Mono.just(buffer));
- });
- }
- }
- 复制代码
3.4 自定义鉴权失败Handler
- package com.pluto.gateway.security;
-
- import com.alibaba.fastjson.JSONObject;
- import com.pluto.common.basic.enums.UserStatusCodeEnum;
- import com.pluto.common.basic.utils.ResultVoUtil;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferFactory;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.MediaType;
- import org.springframework.security.access.AccessDeniedException;
- import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
- import org.springframework.stereotype.Component;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
- import java.nio.charset.Charset;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 11:12
- * @description 鉴权管理
- */
- @Component
- public class DefaultAccessDeniedHandler implements ServerAccessDeniedHandler {
-
- @Override
- public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
- return Mono.defer(() -> Mono.just(exchange.getResponse()))
- .flatMap(response -> {
- response.setStatusCode(HttpStatus.OK);
- response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
- DataBufferFactory dataBufferFactory = response.bufferFactory();
- String result = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.PERMISSION_DENIED));
- DataBuffer buffer = dataBufferFactory.wrap(result.getBytes(
- Charset.defaultCharset()));
- return response.writeWith(Mono.just(buffer));
- });
- }
- }
- 复制代码
4.自定义JWT Token认证管理
- package com.pluto.gateway.security;
-
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.context.SecurityContext;
- import org.springframework.security.core.context.SecurityContextImpl;
- import org.springframework.security.web.server.context.ServerSecurityContextRepository;
- import org.springframework.stereotype.Component;
- import org.springframework.util.CollectionUtils;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
- import javax.annotation.Resource;
- import java.util.List;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 16:27
- * @description 存储认证授权的相关信息
- */
- @Component
- public class DefaultSecurityContextRepository implements ServerSecurityContextRepository {
-
- public final static String TOKEN_HEADER = "Authorization";
-
- public final static String BEARER = "Bearer ";
-
- @Resource
- private TokenAuthenticationManager tokenAuthenticationManager;
-
- @Override
- public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
- return Mono.empty();
- }
-
- @Override
- public Mono<SecurityContext> load(ServerWebExchange exchange) {
- ServerHttpRequest request = exchange.getRequest();
- List<String> headers = request.getHeaders().get(TOKEN_HEADER);
- if (!CollectionUtils.isEmpty(headers)) {
- String authorization = headers.get(0);
- if (StringUtils.isNotEmpty(authorization)) {
- String token = authorization.substring(BEARER.length());
- if (StringUtils.isNotEmpty(token)) {
- return tokenAuthenticationManager.authenticate(
- new UsernamePasswordAuthenticationToken(token, null)
- ).map(SecurityContextImpl::new);
- }
- }
- }
- return Mono.empty();
- }
- }
- 复制代码
- package com.pluto.gateway.security;
-
- import com.pluto.common.basic.utils.JwtTokenUtil;
- import org.springframework.context.annotation.Primary;
- import org.springframework.security.authentication.ReactiveAuthenticationManager;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.stereotype.Component;
- import reactor.core.publisher.Mono;
- import java.util.Collection;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 13:23
- * @description token 认证处理
- */
- @Component
- @Primary
- public class TokenAuthenticationManager implements ReactiveAuthenticationManager {
-
- @Override
- @SuppressWarnings("unchecked")
- public Mono<Authentication> authenticate(Authentication authentication) {
- return Mono.just(authentication)
- .map(auth -> JwtTokenUtil.parseJwtRsa256(auth.getPrincipal().toString()))
- .map(claims -> {
- Collection<? extends GrantedAuthority> roles = (Collection<? extends GrantedAuthority>) claims.get("roles");
- return new UsernamePasswordAuthenticationToken(
- claims.getSubject(),
- null,
- roles
- );
- });
- }
- }
- 复制代码
5.自定义鉴权管理
- package com.pluto.gateway.security;
-
- import com.alibaba.fastjson.JSONObject;
- import com.pluto.common.basic.enums.UserStatusCodeEnum;
- import com.pluto.common.basic.utils.ResultVoUtil;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.security.access.AccessDeniedException;
- import org.springframework.security.authorization.AuthorizationDecision;
- import org.springframework.security.authorization.ReactiveAuthorizationManager;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.web.server.authorization.AuthorizationContext;
- import org.springframework.stereotype.Component;
- import org.springframework.util.AntPathMatcher;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
- import java.util.Collection;
-
- /**
- * @author ShiLei
- * @version 1.0.0
- * @date 2021/3/11 13:10
- * @description 用户权限鉴权处理
- */
- @Component
- @Slf4j
- public class DefaultAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
-
- private final AntPathMatcher antPathMatcher = new AntPathMatcher();
-
- @Override
- public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext authorizationContext) {
- return authentication.map(auth -> {
- ServerWebExchange exchange = authorizationContext.getExchange();
- ServerHttpRequest request = exchange.getRequest();
- Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
- for (GrantedAuthority authority : authorities) {
- String authorityAuthority = authority.getAuthority();
- String path = request.getURI().getPath();
- // TODO
- // 查询用户访问所需角色进行对比
- if (antPathMatcher.match(authorityAuthority, path)) {
- log.info(String.format("用户请求API校验通过,GrantedAuthority:{%s} Path:{%s} ", authorityAuthority, path));
- return new AuthorizationDecision(true);
- }
- }
- return new AuthorizationDecision(false);
- }).defaultIfEmpty(new AuthorizationDecision(false));
- }
-
- @Override
- public Mono<Void> verify(Mono<Authentication> authentication, AuthorizationContext object) {
- return check(authentication, object)
- .filter(AuthorizationDecision::isGranted)
- .switchIfEmpty(Mono.defer(() -> {
- String body = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.PERMISSION_DENIED));
- return Mono.error(new AccessDeniedException(body));
- })).flatMap(d -> Mono.empty());
- }
- }
- 复制代码
2.springsecruity密码判断
下面看看是哪里进行的密码比较
1 /spring-security-core-5.1.4.RELEASE-sources.jar!/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java
- public Authentication authenticate(Authentication authentication)
- throws AuthenticationException {
-
- ......
- try {
- preAuthenticationChecks.check(user);
- // 重点看 additionalAuthenticationChecks 密码判断
- additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);
- }
- catch (AuthenticationException exception) {
- if (cacheWasUsed) {
- // There was a problem, so try again after checking
- // we're using latest data (i.e. not from the cache)
- cacheWasUsed = false;
- user = retrieveUser(username,
- (UsernamePasswordAuthenticationToken) authentication);
- preAuthenticationChecks.check(user);
- additionalAuthenticationChecks(user,
- (UsernamePasswordAuthenticationToken) authentication);
- }
- else {
- throw exception;
- }
- }
-
-
- postAuthenticationChecks.check(user);
-
-
- ......
-
- return createSuccessAuthentication(principalToReturn, authentication, user);
- }
-
- 2 /spring-security-core-5.1.4.RELEASE-sources.jar!/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
-
- protected 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();
- // 密码比较就在这个地方,前面这个是用户输入的密码,后面这个是数据库存的密码,一致则通过
- if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
- logger.debug("Authentication failed: password does not match stored value");
-
-
- throw new BadCredentialsException(messages.getMessage(
- "AbstractUserDetailsAuthenticationProvider.badCredentials",
- "Bad credentials"));
- }
- }
3.流程
用户信息 还可以存放权限信息
3.尚硅谷springsecurity
3.3两个重要接口
3.3.1认证
3.3.2自定义登入
3.3.3
403设计
3.5注解访问
3.5用户注销
3.6免登陆
密码
4过滤器方式
4.1maven---直接引用--配置
- package com.atguigu.serurity.config;
-
- import com.atguigu.serurity.filter.TokenAuthenticationFilter;
- import com.atguigu.serurity.filter.TokenLoginFilter;
- import com.atguigu.serurity.security.DefaultPasswordEncoder;
- import com.atguigu.serurity.security.TokenLogoutHandler;
- import com.atguigu.serurity.security.TokenManager;
- import com.atguigu.serurity.security.UnauthorizedEntryPoint;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
- 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.builders.WebSecurity;
- import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
- import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
- import org.springframework.security.core.userdetails.UserDetailsService;
-
- /**
- * <p>
- * Security配置类
- * </p>
- *
- * @author qy
- * @since 2019-11-18
- */
- @Configuration
- @EnableWebSecurity
- @EnableGlobalMethodSecurity(prePostEnabled = true)
- public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {
-
- private UserDetailsService userDetailsService;//用户详情服务
- private TokenManager tokenManager;//令牌管理器
- private DefaultPasswordEncoder defaultPasswordEncoder;//默认密码编码器
- private RedisTemplate redisTemplate;//Redis 模板
-
- //令牌网络安全配置
- @Autowired
- public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
- TokenManager tokenManager, RedisTemplate redisTemplate) {
- this.userDetailsService = userDetailsService;
- this.defaultPasswordEncoder = defaultPasswordEncoder;
- this.tokenManager = tokenManager;
- this.redisTemplate = redisTemplate;
- }
-
- /**
- * 配置设置
- * @param http
- * @throws Exception
- */
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- System.out.println("configure(HttpSecurity http)"+http);
- http.exceptionHandling()
- .authenticationEntryPoint(new UnauthorizedEntryPoint())
- .and().csrf().disable()
-
- .authorizeRequests()
- .anyRequest().authenticated()
- .and().logout().logoutUrl("/admin/acl/index/logout")
- .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
- .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
- .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();
- }
-
- /**
- * 密码处理
- * @param auth
- * @throws Exception
- * 身份验证管理器生成器
- */
- @Override
- public void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
- }
-
- /**
- * 配置哪些请求不拦截
- * @param web
- * @throws Exception
- */
- @Override
- public void configure(WebSecurity web) throws Exception {
- web.ignoring().antMatchers("/api/**",
- "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"
- );
- }
- }
4.2 entity
- package com.atguigu.serurity.entity;
-
- import lombok.Data;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.util.StringUtils;
-
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
-
- /**
- * <p>
- * 安全认证用户详情信息
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- @Data
- @Slf4j
- public class SecurityUser implements UserDetails {
-
- //当前登录用户
- private transient User currentUserInfo;
-
- //当前权限
- private List<String> permissionValueList;
-
- public SecurityUser() {
- }
-
- public SecurityUser(User user) {
- if (user != null) {
- this.currentUserInfo = user;
- }
- }
-
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities() {
- Collection<GrantedAuthority> authorities = new ArrayList<>();
- for(String permissionValue : permissionValueList) {
- if(StringUtils.isEmpty(permissionValue)) continue;
- SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
- authorities.add(authority);
- }
-
- return authorities;
- }
-
- @Override
- public String getPassword() {
- return currentUserInfo.getPassword();
- }
-
- @Override
- public String getUsername() {
- return currentUserInfo.getUsername();
- }
-
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
-
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
-
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
- }
- package com.atguigu.serurity.entity;
-
- import io.swagger.annotations.ApiModel;
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Builder;
- import lombok.Data;
-
- import java.io.Serializable;
-
- /**
- * <p>
- * 用户实体类
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- @Data
- @ApiModel(description = "用户实体类")
- public class User implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @ApiModelProperty(value = "微信openid")
- private String username;
-
- @ApiModelProperty(value = "密码")
- private String password;
-
- @ApiModelProperty(value = "昵称")
- private String nickName;
-
- @ApiModelProperty(value = "用户头像")
- private String salt;
-
- @ApiModelProperty(value = "用户签名")
- private String token;
-
- }
-
-
-
4.3 filter
4.3.1 访问过滤器 获取request--token
- package com.atguigu.serurity.filter;
-
- import com.atguigu.commonutils.R;
- import com.atguigu.commonutils.ResponseUtil;
- import com.atguigu.serurity.security.TokenManager;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.security.authentication.AuthenticationManager;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
- import org.springframework.util.StringUtils;
-
- 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.ArrayList;
- import java.util.Collection;
- import java.util.List;
-
- /**
- * <p>
- * 访问过滤器
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
- private TokenManager tokenManager;
- private RedisTemplate redisTemplate;
-
- public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
- super(authManager);
- this.tokenManager = tokenManager;
- this.redisTemplate = redisTemplate;
- }
-
- @Override
- protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
- throws IOException, ServletException {
- logger.info("=======TokenAuthenticationFilter-doFilterInternal=========="+req.getRequestURI());
- System.out.println("req.getRequestURI().indexOf(\"admin\")"+req.getRequestURI().indexOf("admin"));
- System.out.println("doFilterInternal-req"+req);
- System.out.println("doFilterInternal-req.getRequestURI()"+req.getRequestURI());
- // if(req.getRequestURI().indexOf("admin") == 1) {
- // chain.doFilter(req, res);
- // return;
- // }
-
- UsernamePasswordAuthenticationToken authentication = null;
- try {
- authentication = getAuthentication(req);
- System.out.println("doFilterInternal-authentication"+authentication);
- } catch (Exception e) {
- ResponseUtil.out(res, R.error());
- }
-
- if (authentication != null) {
- SecurityContextHolder.getContext().setAuthentication(authentication);
- } else {
- ResponseUtil.out(res, R.error());
- }
- /*将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,
- 如果没有filter那就是你请求的资源。 一般filter都是一个链,web.xml 里面配置了几个就有几个。
- 一个一个的连在一起 request -> filter1 -> filter2 ->filter3 -> .... -> request resource.
- */
- chain.doFilter(req, res);
- }
-
- private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
- // token置于header里
- String token = request.getHeader("token");
- if (token != null && !"".equals(token.trim())) {
- String userName = tokenManager.getUserFromToken(token);
-
- List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
- Collection<GrantedAuthority> authorities = new ArrayList<>();
- for(String permissionValue : permissionValueList) {
- if(StringUtils.isEmpty(permissionValue)) continue;
- SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
- authorities.add(authority);
- }
-
- if (!StringUtils.isEmpty(userName)) {
- return new UsernamePasswordAuthenticationToken(userName, token, authorities);
- }
- return null;
- }
- return null;
- }
- }
4.3.2 登录过滤器 成功 获取token 保存redis
- package com.atguigu.serurity.filter;
-
- import com.atguigu.commonutils.R;
- import com.atguigu.commonutils.ResponseUtil;
- import com.atguigu.serurity.entity.SecurityUser;
- import com.atguigu.serurity.entity.User;
- import com.atguigu.serurity.security.TokenManager;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.security.authentication.AuthenticationManager;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
- import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-
- 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.ArrayList;
-
- /**
- * <p>
- * 登录过滤器,继承UsernamePasswordAuthenticationFilter,对用户名密码进行登录校验
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
-
- private AuthenticationManager authenticationManager;
- private TokenManager tokenManager;
- private RedisTemplate redisTemplate;
-
- public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
- this.authenticationManager = authenticationManager;
- this.tokenManager = tokenManager;
- this.redisTemplate = redisTemplate;
- this.setPostOnly(false);
- this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login","POST"));
- }
-
- @Override
- public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
- throws AuthenticationException {
- try {
- User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
-
- return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- }
-
- /**
- * 登录成功
- * @param req
- * @param res
- * @param chain
- * @param auth
- * @throws IOException
- * @throws ServletException
- */
- @Override
- protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
- Authentication auth) throws IOException, ServletException {
- SecurityUser user = (SecurityUser) auth.getPrincipal();
- String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
- redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
-
- ResponseUtil.out(res, R.ok().data("token", token));
- }
-
- /**
- * 登录失败
- * @param request
- * @param response
- * @param e
- * @throws IOException
- * @throws ServletException
- */
- @Override
- protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
- AuthenticationException e) throws IOException, ServletException {
- ResponseUtil.out(response, R.error());
- }
- }
4.4密码的处理方法类型
- package com.atguigu.serurity.security;
-
- import com.atguigu.commonutils.MD5;
- import org.springframework.security.crypto.password.PasswordEncoder;
- import org.springframework.stereotype.Component;
-
- /**
- * <p>
- * t密码的处理方法类型
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- @Component
- public class DefaultPasswordEncoder implements PasswordEncoder {
-
- public DefaultPasswordEncoder() {
- this(-1);
- }
-
- /**
- * @param strength
- * the log rounds to use, between 4 and 31
- */
- public DefaultPasswordEncoder(int strength) {
-
- }
- /*
- * 密码加密
- * */
- public String encode(CharSequence rawPassword) {
- return MD5.encrypt(rawPassword.toString());
- }
-
- /*
- * 密码是否相等
- * */
- public boolean matches(CharSequence rawPassword, String encodedPassword) {
-
- return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));
- }
- }
4.4退出
- package com.atguigu.serurity.security;
-
- import com.atguigu.commonutils.R;
- import com.atguigu.commonutils.ResponseUtil;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.web.authentication.logout.LogoutHandler;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- /**
- * <p>
- * 登出业务逻辑类
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- public class TokenLogoutHandler implements LogoutHandler {
-
- private TokenManager tokenManager;
- private RedisTemplate redisTemplate;
-
- public TokenLogoutHandler(TokenManager tokenManager, RedisTemplate redisTemplate) {
- this.tokenManager = tokenManager;
- this.redisTemplate = redisTemplate;
- }
-
- @Override
- public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
- String token = request.getHeader("token");
- if (token != null) {
- tokenManager.removeToken(token);
-
- //清空当前用户缓存中的权限数据
- String userName = tokenManager.getUserFromToken(token);
- redisTemplate.delete(userName);
- }
- ResponseUtil.out(response, R.ok());
- }
-
- }
4.5token生成
- package com.atguigu.serurity.security;
-
- import io.jsonwebtoken.CompressionCodecs;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- import org.springframework.stereotype.Component;
-
- import java.util.Date;
-
- /**
- * <p>
- * token管理
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- @Component
- public class TokenManager {
-
- private long tokenExpiration = 24*60*60*1000;
- private String tokenSignKey = "123456";
-
- public String createToken(String username) {
- String token = Jwts.builder().setSubject(username)
- .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
- .signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();
- return token;
- }
-
- public String getUserFromToken(String token) {
- String user = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject();
- return user;
- }
-
- public void removeToken(String token) {
- //jwttoken无需删除,客户端扔掉即可。
- }
-
- }
4.6未授权
- package com.atguigu.serurity.security;
-
- import com.atguigu.commonutils.R;
- import com.atguigu.commonutils.ResponseUtil;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.AuthenticationEntryPoint;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /**
- * <p>
- * 未授权的统一处理方式
- * </p>
- *
- * @author qy
- * @since 2019-11-08
- */
- public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
-
- @Override
- public void commence(HttpServletRequest request, HttpServletResponse response,
- AuthenticationException authException) throws IOException, ServletException {
-
- ResponseUtil.out(response, R.error());
- }
- }
4.7 XML
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>commont</artifactId>
- <groupId>com.atguigu</groupId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>spring_security</artifactId>
-
- <dependencies>
- <dependency>
- <groupId>com.atguigu</groupId>
- <artifactId>comment_utils</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
-
- <!-- Spring Security依赖 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
-
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- </dependency>
- </dependencies>
- </project>
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>guli_parent</artifactId>
- <groupId>com.atguigu</groupId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>commont</artifactId>
- <packaging>pom</packaging>
- <modules>
- <module>service_base</module>
- <module>comment_utils</module>
- <module>spring_security</module>
- </modules>
-
- <dependencies>
- <!-- redis -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
-
- <!-- spring2.X集成redis所需common-pool2-->
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-pool2</artifactId>
- <version>2.6.0</version>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <scope>provided </scope>
- </dependency>
-
- <!--mybatis-plus-->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <scope>provided </scope>
- </dependency>
-
- <!--lombok用来简化实体类:需要安装lombok插件-->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <scope>provided </scope>
- </dependency>
-
- <!--swagger-->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
- <scope>provided </scope>
- </dependency>
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
- <scope>provided </scope>
- </dependency>
-
- <!-- redis -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
-
- <!-- spring2.X集成redis所需common-pool2
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-pool2</artifactId>
- <version>2.6.0</version>
- </dependency>-->
- </dependencies>
-
- </project>
4.7 jwt
- package com.atguigu.commonutils;
-
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.Jws;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.util.StringUtils;
-
- import javax.servlet.http.HttpServletRequest;
- import java.util.Date;
-
- /**
- * @author helen
- * @since 2019/10/16
- * 生成字符串,包含用户信息,
- * jwt生成包含三部分:1头2.有效荷载3.签名哈希 防伪标志
- */
- public class JwtUtils {
-
- public static final long EXPIRE = 1000 * 60 * 60 * 24;//token过期时间
- public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";//密钥
-
- public static String getJwtToken(String id, String nickname){
-
- String JwtToken = Jwts.builder()
- //第一步分
- .setHeaderParam("typ", "JWT")
- .setHeaderParam("alg", "HS256")
-
- //第二部分
- .setSubject("guli-user")
- .setIssuedAt(new Date())
- .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
-
- //第三部分 token主体
- .claim("id", id)
- .claim("nickname", nickname)
-
- .signWith(SignatureAlgorithm.HS256, APP_SECRET)
- .compact();
-
- return JwtToken;
- }
-
- /**
- * 判断token是否存在与有效
- * @param jwtToken
- * @return
- */
- public static boolean checkToken(String jwtToken) {
- if(StringUtils.isEmpty(jwtToken)) return false;
- try {
- Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * 判断token是否存在与有效
- * @param request
- * @return
- */
- public static boolean checkToken(HttpServletRequest request) {
- try {
- String jwtToken = request.getHeader("token");
- System.out.println("jwtToken"+jwtToken);
- if(StringUtils.isEmpty(jwtToken)) return false;
- Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * 根据token获取会员id
- * @param request
- * @return
- */
- public static String getMemberIdByJwtToken(HttpServletRequest request) {
- String jwtToken = request.getHeader("token");
- if(StringUtils.isEmpty(jwtToken))
- return "";
- Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
- Claims claims = claimsJws.getBody();
- System.out.println("claims:"+claims);
- return (String)claims.get("id");
-
-
- }
- }
4.8 MD5
- package com.atguigu.commonutils;
-
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
-
-
- public final class MD5 {
-
- public static String encrypt(String strSrc) {
- try {
- char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- byte[] bytes = strSrc.getBytes();
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(bytes);
- bytes = md.digest();
- System.out.println("bytes"+bytes);
- int j = bytes.length;
- System.out.println("j"+j);
- char[] chars = new char[j * 2];
- int k = 0;
- for (int i = 0; i < bytes.length; i++) {
- byte b = bytes[i];
- System.out.println(" bytes[i]"+ bytes[i]);
- //转化hexChars
- chars[k++] = hexChars[b >>> 4 & 0xf];
- chars[k++] = hexChars[b & 0xf];
-
- }
-
- return new String(chars);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- throw new RuntimeException("MD5加密出错!!+" + e);
- }
- }
-
- public static void main(String[] args) {
- System.out.println(MD5.encrypt("111111"));
- }
-
- }
4.9 R
- package com.atguigu.commonutils;
-
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Data;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @Data
- public class R {
- @ApiModelProperty(value = "是否成功")
- private Boolean success;
-
- @ApiModelProperty(value = "返回码")
- private Integer code;
-
- @ApiModelProperty(value = "返回消息")
- private String message;
-
- @ApiModelProperty(value = "返回数据")
- private Map<String, Object> data = new HashMap<String, Object>();
-
- //构造器私有化
- private R() {
- }
-
- //成功静态方法
- public static R ok() {
- R r = new R();
- r.setSuccess(true);
- r.setCode(ResultCode.SUCCESS);
- r.setMessage("成功");
- return r;
- }
-
- //失败静态方法
- public static R error() {
- R r = new R();
- r.setSuccess(false);
- r.setCode(ResultCode.ERROR);
- r.setMessage("失败");
- return r;
- }
-
- public R success(Boolean success) {
- this.setSuccess(success);
- return this;
- }
-
- public R message(String message) {
- this.setMessage(message);
- return this;
- }
-
- public R code(Integer code) {
- this.setCode(code);
- return this;
- }
-
- public R data(String key, Object value) {
- this.data.put(key, value);
- return this;
- }
-
- public R data(Map<String, Object> map) {
- this.setData(map);
- return this;
- }
- }