赞
踩
token的鉴权机制:http协议也是无状态的,不需要在服务端去保留用户的认证信息或者会话信息。这也就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录
鉴权流程:简单来说就是服务器根据前端传来的用户名与密码生成token并返回前端,前端之后的请求都会携带该cookie来进行执行操作认证。
这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS
JWT
(JSON WEB TOKEN)是由三段信息构成的,将这三段信息文本用.
链接一起就构成了Jwt字符串.
是一个强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的实际标准。Spring Security是一个可以为Java应用程序提供全面安全服务的框架。同时,它也可以轻松扩展以满足自定义需求。
主要功能
Authentication (认证),就是用户登录
Authorization (授权):一旦身份验证成功,判断用户拥有什么权限,可以访问什么资源
防止跨站请求伪造(CSRF):Spring Security提供了内置的防护机制,可以防止跨站请求伪造攻击。
密码存储:Spring Security提供了多种密码存储格式,包括明文、加密和哈希。
集成其他安全框架:Spring Security可以与其他安全框架如OAuth2、JWT等进行集成,以提供更全面的安全解决方案。
SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。
SecurityContextPersistenceFilter:每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中。
LogoutFilter:用于处理退出登录。
UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。
BasicAuthenticationFilter:检测和处理 http basic 认证。
ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。
FilterSecurityInterceptor:负责权限校验的过滤器,可以看做过滤器链的出口。
首先前端一样是把登录信息发送给后端,后端查询数据库校验用户的账号和密码是否正确,正确的话则使用jwt生成token,并且返回给前端。以后前端每次请求时,都需要携带token,后端获取token后,使用jwt进行验证用户的token是否无效或过期,验证成功后才去做相应的逻辑。
pom.xml
文件中添加以下依赖项:- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
- </dependencies>
创建Redis配置类
- @Configuration
- public class RedisConfig {
-
- @Value("${spring.redis.host}")
- private String host;
-
- @Value("${spring.redis.port}")
- private int port;
-
- @Bean
- public JedisConnectionFactory jedisConnectionFactory() {
- return new JedisConnectionFactory(new RedisStandaloneConfiguration(host, port));
- }
-
- @Bean
- public RedisTemplate<String, Object> redisTemplate() {
- final RedisTemplate<String, Object> template = new RedisTemplate<>();
- template.setConnectionFactory(jedisConnectionFactory());
- return template;
- }
- }
创建 JwtTokenUtil
类,用于生成和验证JWT令牌。
- @Component
- public class JwtTokenUtil implements Serializable {
-
- private static final long serialVersionUID = -2550185165626007488L;
-
- private static final String secret = "mySecret";
-
- public String getUsernameFromToken(String token) {
- return getClaimFromToken(token, Claims::getSubject);
- }
-
- public Date getExpirationDateFromToken(String token) {
- return getClaimFromToken(token, Claims::getExpiration);
- }
-
- public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
- final Claims claims = getAllClaimsFromToken(token);
- return claimsResolver.apply(claims);
- }
-
- private Claims getAllClaimsFromToken(String token) {
- return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
- }
-
- private Boolean isTokenExpired(String token) {
- final Date expiration = getExpirationDateFromToken(token);
- return expiration.before(new Date());
- }
-
- public String generateToken(UserDetails userDetails) {
- Map<String, Object> claims = new HashMap<>();
- return doGenerateToken(claims, userDetails.getUsername());
- }
-
- private String doGenerateToken(Map<String, Object> claims, String subject) {
- return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
- .setExpiration(new Date(System.currentTimeMillis() + 5 * 60 * 60 * 1000))
- .signWith(SignatureAlgorithm.HS512, secret).compact();
- }
-
- public Boolean validateToken(String token, UserDetails userDetails) {
- final String username = getUsernameFromToken(token);
- return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
- }
- }
创建 JwtAuthenticationEntryPoint
类,用于处理未经授权的请求。
- @Component
- public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
-
- private static final long serialVersionUID = -7858869558953243875L;
-
- @Override
- public void commence(HttpServletRequest request, HttpServletResponse response,
- AuthenticationException authException) throws IOException {
-
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
- }
- }
创建 JwtRequestFilter
类,用于解析和验证JWT令牌。
- @Component
- public class JwtRequestFilter extends OncePerRequestFilter {
-
- @Autowired
- private MyUserDetailsService myUserDetailsService;
-
- @Autowired
- private JwtTokenUtil jwtTokenUtil;
-
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
- throws ServletException, IOException {
-
- final String requestTokenHeader = request.getHeader("Authorization");
-
- String username = null;
- String jwtToken = null;
-
- if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
- jwtToken = requestTokenHeader.substring(7);
- try {
- username = jwtTokenUtil.getUsernameFromToken(jwtToken);
- } catch (IllegalArgumentException e) {
- System.out.println("Unable to get JWT Token");
- } catch (ExpiredJwtException e) {
- System.out.println("JWT Token has expired");
- }
- } else {
- logger.warn("JWT Token does not begin with Bearer String");
- }
-
- if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
-
- UserDetails userDetails = this.myUserDetailsService.loadUserByUsername(username);
-
- if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
-
- UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
- userDetails, null, userDetails.getAuthorities());
- usernamePasswordAuthenticationToken
- .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
-
- SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
- }
- }
- chain.doFilter(request, response);
- }
- }
配置Spring Security
- @Configuration
- @EnableWebSecurity
- public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Autowired
- private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
-
- @Autowired
- private UserDetailsService jwtUserDetailsService;
-
- @Autowired
- private JwtRequestFilter jwtRequestFilter;
-
- @Autowired
- public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
- }
-
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
-
- @Bean
- @Override
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
- }
-
- @Override
- protected void configure(HttpSecurity httpSecurity) throws Exception {
- httpSecurity.csrf().disable()
- .authorizeRequests().antMatchers("/authenticate").permitAll().
- anyRequest().authenticated().and().
- exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-
- httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。