当前位置: 首页 > wzjs >正文

微信自建小程序seo排名优化怎样

微信自建小程序,seo排名优化怎样,网站刷新新前台是什么意思,大淘客优惠券网站是怎么做的背景 前一个项目基于springboot2做的后台服务,使用到了spring security做权限验证,token是用java生成的uuid,把token信息存储到了redis服务中。 新的项目计划使用springboot3,且希望使用JWT实现token,以下重新记录下…

背景

前一个项目基于springboot2做的后台服务,使用到了spring security做权限验证,token是用java生成的uuid,把token信息存储到了redis服务中。

新的项目计划使用springboot3,且希望使用JWT实现token,以下重新记录下实现思路。

项目依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.9</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.jy.bike</groupId><artifactId>bike</artifactId><version>0.0.1-SNAPSHOT</version><name>bike</name><description>Demo project for Spring Boot</description><url/><properties><mysql-connector>8.0.18</mysql-connector><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.10</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector}</version></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.5</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

Spring Security的鉴权原理

通过jwt生成token后,后续接口请求时,在header中传入jwt token,通过自定义JwtAuthenticationFilter获取登录用户信息,并放在spring security context里。由后续UsernamePasswordAuthenticationFilter验证和拦截鉴权

实现步骤

1.配置SecurityConfiguration

其中包括:白名单放行(swagger,login等资源),自定义JwtAuthenticationFilter并放在UsernamePasswordAuthenticationFilter之前,自定义UserService并通过其userDetailsService方法获取用户信息,使用BCryptPasswordEncoder密文验证账号密码,

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {@Autowiredprivate JwtAuthenticationFilter jwtAuthenticationFilter;@Autowiredprivate UserService userService;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {// 关闭跨站请求http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(request ->// 配置放行白名单request.requestMatchers("login", "logout").permitAll().requestMatchers("swagger-ui/*", "v3/api-docs", "v3/api-docs/*", "/druid/**").permitAll().anyRequest().authenticated())// 禁用session.sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS)).authenticationProvider(authenticationProvider()).addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic AuthenticationProvider authenticationProvider() {DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();authProvider.setUserDetailsService(userService.userDetailsService());authProvider.setPasswordEncoder(passwordEncoder());return authProvider;}@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {return config.getAuthenticationManager();}
}

2.定义一个实体类,继承UserDetails类

用于放在spring security context里,里面包括登录账号的名称,密码,权限,状态等

public class LoginUserDetails implements UserDetails {private static final long serialVersionUID = 1L;private User user;public LoginUserDetails(User user) {this.user = user;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return List.of();}@Overridepublic String getPassword() {return user.getPassword();}@Overridepublic String getUsername() {return user.getName();}@Overridepublic boolean isEnabled() {return user.isEnabled();}
}

3.实现一个UserService,通过其loadUserByUsername获取用户

实际应该用username查询数据库获取,这里写死一个用户,并传入经过BCryptPasswordEncoder加密后的密文(原文是123456)

@Service
public class UserService {public UserDetailsService userDetailsService() {return new UserDetailsService() {@Overridepublic UserDetails loadUserByUsername(String username) {User curUser = new User();curUser.setName("madixin");                curUser.setPassword("$2a$10$Yt3wAk1P1aZZsJKnjGbnQehJD8F80tLS.tsenpPTC1kMrMdbjvN7.");curUser.setEnabled(true);LoginUserDetails loginUser = new LoginUserDetails(curUser);return loginUser;}};}
}

4.实现一个jwtservice,用于把用户信息加密和解密成token

@Service
public class JwtService implements IJwtService {@Value("${token.signing.key}")private String jwtSigningKey;@Overridepublic String extractUserName(String token) {return extractClaim(token, Claims::getSubject);}@Overridepublic String generateToken(UserDetails userDetails) {return generateToken(new HashMap<>(), userDetails);}@Overridepublic boolean isTokenValid(String token, UserDetails userDetails) {final String userName = extractUserName(token);return (userName.equals(userDetails.getUsername())) && !isTokenExpired(token);}private <T> T extractClaim(String token, Function<Claims, T> claimsResolvers) {final Claims claims = extractAllClaims(token);return claimsResolvers.apply(claims);}private String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {return Jwts.builder().setClaims(extraClaims).setSubject(userDetails.getUsername()).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 24)).signWith(getSigningKey(), SignatureAlgorithm.HS256).compact();}private boolean isTokenExpired(String token) {return extractExpiration(token).before(new Date());}private Date extractExpiration(String token) {return extractClaim(token, Claims::getExpiration);}private Claims extractAllClaims(String token) {return Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();}private Key getSigningKey() {byte[] keyBytes = Decoders.BASE64.decode(jwtSigningKey);return Keys.hmacShaKeyFor(keyBytes);}
}

5.实现自己的login接口,验证登录账号和密码是否正确,是否禁用,如果通过,则使用jwtservice生成token返回。

调用authenticationManager.authenticate时,会自动调用UserService的loadUserByUsername获取用户和校验密码

@RestController
public class LoginController {private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);@Autowiredprivate LoginService loginService;/*** 登录方法** @param loginDto 登录信息* @return 结果*/@PostMapping("/login")public ResponseResult<String> login(@RequestBody LoginDto loginDto) {try {// 返回JWT令牌return ResponseResult.success(loginService.login(loginDto.getPhone(), loginDto.getPassword()));} catch (BikeBaseException e) {LOGGER.error(e.getMessage());return ResponseResult.fail(e.getErrorCode());}}
}@Service
public class LoginService {private static final Logger LOGGER = LoggerFactory.getLogger(LoginService.class);@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate JwtService jwtService;public String login(String username, String password) throws BikeBaseException {// 该方法会去调用UserDetailsService.loadUserByUsernameAuthentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));LoginUserDetails loginUser = (LoginUserDetails) authentication.getPrincipal();if (loginUser == null){throw new BikeBaseException(ErrorCode.ILLEGAL_AUTHENTICATE);// 认证失败}return jwtService.generateToken(loginUser);}public void logout() throws BikeBaseException {}
}

6.自实现JwtAuthenticationFilter(第一步已配置在UsernamePasswordAuthenticationFilter前),从header中获取token,如果验证通过,则把用户信息放在spring security context里。

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {@Autowiredprivate JwtService jwtService;@Autowiredprivate UserService userService;@Overrideprotected void doFilterInternal(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response, @NonNull FilterChain filterChain)throws ServletException, IOException {final String authHeader = request.getHeader("Authorization");final String jwt;final String userEmail;if (StringUtils.isEmpty(authHeader) || !StringUtils.startsWith(authHeader, "Bearer ")) {filterChain.doFilter(request, response);return;}jwt = authHeader.substring(7);userEmail = jwtService.extractUserName(jwt);if (StringUtils.isNotEmpty(userEmail)&& SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = userService.userDetailsService().loadUserByUsername(userEmail);if (jwtService.isTokenValid(jwt, userDetails)) {SecurityContext context = SecurityContextHolder.createEmptyContext();UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));context.setAuthentication(authToken);SecurityContextHolder.setContext(context);}}filterChain.doFilter(request, response);}
}

7.自定义权限异常返回

实现AuthenticationEntryPoint和AccessDeniedHandler,通过response写会统一的异常返回。

@Component
public class CustomerAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");ServletOutputStream outputStream = response.getOutputStream();ObjectMapper objectMapper = new ObjectMapper();outputStream.write(objectMapper.writeValueAsString(ResponseResult.fail(ErrorCode.ILLEGAL_AUTHENTICATE)).getBytes(StandardCharsets.UTF_8));outputStream.flush();outputStream.close();}
}@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {response.setContentType("application/json;charset=utf-8");ServletOutputStream outputStream = response.getOutputStream();ObjectMapper objectMapper = new ObjectMapper();outputStream.write(objectMapper.writeValueAsString(ResponseResult.fail(ErrorCode.ILLEGAL_AUTHENTICATE)).getBytes(StandardCharsets.UTF_8));outputStream.flush();outputStream.close();}
}

在SecurityConfiguration中配置异常处理

http.exceptionHandling(configurer -> {configurer.authenticationEntryPoint(restAuthenticationEntryPoint);configurer.accessDeniedHandler(customerAccessDeniedHandler);
});

8.基于角色,更细粒度的控制每个接口的权限

通过在每个接口,配置@PreAuthorize装饰器实现,如

@PreAuthorize("@ss.hasPermi('sysadmin,company_admin,project_admin,worker')")

具体代码就不附上了。

参考

源码:https://github.com/buingoctruong/springboot3-springsecurity6-jwt

视频:2024最新SpringSecurity6安全框架教程-Spring Security+JWT实现项目级前端分离认证_哔哩哔哩_bilibili

http://www.dtcms.com/wzjs/233825.html

相关文章:

  • 网站开发零基础培训学校动态网站设计毕业论文
  • wordpress模板目录结构seo推广策略
  • 美国有网站建设公司吗泉州百度开户
  • wordpress 摘要 格式北京aso优化
  • 做网站推广怎么找客户重庆疫情最新数据
  • 洛阳网站建设 培训软文推广方案
  • 哪些是网站建设google搜索引擎优化
  • 阳西哪里有做网站推广普通话活动方案
  • 网站后台更新前台更新不2022年最近一周新闻大事
  • 企业网站开发建设委托合同seo专员
  • 客服 咨询系统5年网站seo优化公司
  • 建设网上银行官方网站seo具体是什么
  • 网站优化推广排名网时代教育培训机构怎么样
  • vue 做网站 seoseo优化效果
  • 医院ppt模板免费下载 素材谷歌排名优化
  • 燃烧学课程网站建设seo新手快速入门
  • 娄底网站建设79ld房产网站建设
  • 如何利用源代码做网站网站推广的基本方法有
  • 动易做网站如何今日热搜榜前十名
  • 短信轰炸网站开发山东关键词快速排名
  • 做期货财经网站需要哪些资质营销策略有哪些方面
  • 山东企业网站建设谷歌推广优化
  • 企业网站美工设计seo竞争对手分析
  • 成都网站空间创新互联百度推广投诉热线
  • 代做广联达 的网站今日重大军事新闻
  • 武汉设计工程学院成龙云南seo
  • 苏州网站设计电话网络优化的基本方法
  • 简单 大气 网站模版百度搜索量怎么查
  • 个人 中小企业公司网站建设方案百度推广联盟
  • 靖江做网站的单位网络营销服务企业有哪些