Sprint Boot使用OAuth和JWT实现身份认证【二】

举报
清雨小竹 发表于 2022/09/25 01:15:38 2022/09/25
1.4k+ 0 0
【摘要】 上一篇文章已经实现了自定义获取token方法和自定义过滤器,本篇文章对自定义类进行封装: 文件结构: 依赖: dependencies { compile('com.github.wenhao:jpa-spec:3.1.1') compile('io.springfox:springfox-swagger2:2.2....

上一篇文章已经实现了自定义获取token方法和自定义过滤器,本篇文章对自定义类进行封装:

文件结构:


依赖:


      dependencies {
         compile('com.github.wenhao:jpa-spec:3.1.1')
          compile('io.springfox:springfox-swagger2:2.2.2')
          compile('io.springfox:springfox-swagger-ui:2.2.2')
          compile 'io.jsonwebtoken:jjwt:0.9.0'
          compile 'com.alibaba:fastjson:1.2.44'
          compile('org.springframework.security:spring-security-jwt')
          compile('org.springframework.boot:spring-boot-starter-security')
          compile('org.springframework.security.oauth:spring-security-oauth2')
      	compile('org.springframework.boot:spring-boot-starter-data-jpa')
      	compile('org.springframework.boot:spring-boot-starter-jdbc')
      	compile('org.springframework.boot:spring-boot-starter-web')
      	runtime('mysql:mysql-connector-java')
      	providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
      	testCompile('org.springframework.boot:spring-boot-starter-test')
      }
  
 


      package com.yf.gyy.OAuthConfig;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      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.EnableWebSecurity;
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
      import org.springframework.security.config.http.SessionCreationPolicy;
      import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
      @Configuration
      @EnableWebSecurity
      @EnableGlobalMethodSecurity(prePostEnabled = true)
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
         @Override
         protected void configure(HttpSecurity httpSecurity) throws Exception {
          	httpSecurity
          	.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
          	.csrf().disable()
          	.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
               .requestMatchers().anyRequest();
          }
         @Bean
         public JWTAuthenticationFilter authenticationTokenFilterBean() throws Exception {
             return new JWTAuthenticationFilter();
          }
      }
  
 

      package com.yf.gyy.OAuthConfig;
      import java.io.IOException;
      import javax.servlet.FilterChain;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
      import org.springframework.security.core.context.SecurityContextHolder;
      import org.springframework.security.core.userdetails.UserDetails;
      import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
      import org.springframework.stereotype.Component;
      import org.springframework.web.filter.OncePerRequestFilter;
      import io.jsonwebtoken.Claims;
      import io.jsonwebtoken.Jwts;
      @Component
      public class JWTAuthenticationFilter extends OncePerRequestFilter {
         @Autowired
         private JWTUtils jwtTokenUtil;
         @Override
         protected void doFilterInternal(
       HttpServletRequest request,
       HttpServletResponse response,
       FilterChain chain) throws ServletException, IOException {
         	String tokenHeader = "Authorization";
         	String tokenHead = "Bearer ";
             String authHeader = request.getHeader(tokenHeader);
             if (authHeader != null && authHeader.startsWith(tokenHead)) {
                 final String authToken = authHeader.substring(tokenHead.length());
                 Claims claims = Jwts.parser()
                          .setSigningKey(JWTUtils.secret)
                          .parseClaimsJws(authToken)
                          .getBody();
                 UserDetails userDetails = jwtTokenUtil.getUserFromToken(claims);
                 if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                     UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                      authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                      SecurityContextHolder.getContext().setAuthentication(authentication);
                  }
              }
              chain.doFilter(request, response);
          }
      }
  
 


      package com.yf.gyy.OAuthConfig;
      import java.util.Collection;
      import org.springframework.security.core.GrantedAuthority;
      import org.springframework.security.core.userdetails.UserDetails;
      public class JWTUserDetails implements UserDetails {
     	private String userId;
         private String password;
         private final String username;
         private final Collection<? extends GrantedAuthority> authorities;
         private final boolean accountNonExpired;
         private final boolean accountNonLocked;
         private final boolean credentialsNonExpired;
         private final boolean enabled;
         public JWTUserDetails(String userId, String username, String password, Collection<? extends GrantedAuthority> authorities) {
             this(userId, username, password, true, true, true, true, authorities);
          }
         public JWTUserDetails(String userId, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
             if (username != null && !"".equals(username) && password != null) {
                 this.userId = userId;
                 this.username = username;
                 this.password = password;
                 this.enabled = enabled;
                 this.accountNonExpired = accountNonExpired;
                 this.credentialsNonExpired = credentialsNonExpired;
                 this.accountNonLocked = accountNonLocked;
                 this.authorities = authorities;
              } else {
                 throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
              }
          }
         @Override
         public Collection<? extends GrantedAuthority> getAuthorities() {
             return authorities;
          }
         public String getUserId() {
             return userId;
          }
         @Override
         public String getPassword() {
             return password;
          }
         @Override
         public String getUsername() {
             return username;
          }
         @Override
         public boolean isAccountNonExpired() {
             return accountNonExpired;
          }
         @Override
         public boolean isAccountNonLocked() {
             return accountNonLocked;
          }
         @Override
         public boolean isCredentialsNonExpired() {
             return credentialsNonExpired;
          }
         @Override
         public boolean isEnabled() {
             return enabled;
          }
      }
  
 


      package com.yf.gyy.OAuthConfig;
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.Date;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.UUID;
      import org.springframework.security.core.GrantedAuthority;
      import org.springframework.security.core.authority.SimpleGrantedAuthority;
      import org.springframework.security.core.userdetails.UserDetails;
      import org.springframework.stereotype.Component;
      import com.alibaba.fastjson.JSON;
      import io.jsonwebtoken.Claims;
      import io.jsonwebtoken.CompressionCodecs;
      import io.jsonwebtoken.Jwts;
      import io.jsonwebtoken.SignatureAlgorithm;
      @Component
      public class JWTUtils {
         public static final String ROLE_REFRESH_TOKEN = "ROLE_REFRESH_TOKEN";
         private static final String CLAIM_KEY_USER_ID = "user_id";
         private static final String CLAIM_KEY_AUTHORITIES = "scope";
         private static final String CLAIM_KEY_ACCOUNT_ENABLED = "enabled";
         private static final String CLAIM_KEY_ACCOUNT_NON_LOCKED = "non_locked";
         private static final String CLAIM_KEY_ACCOUNT_NON_EXPIRED = "non_expired";
         public static  String secret = "123456";
         private static  Long access_token_expiration = 30000L;
         private static  Long refresh_token_expiration = 30000L;
         /*@Value("${jwt.secret}")
       private String secret;
       @Value("${jwt.access_token.expiration}")
       private Long access_token_expiration;
       @Value("${jwt.refresh_token.expiration}")
       private Long refresh_token_expiration;*/
         private final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;
         public JWTUserDetails getUserFromToken(String token) {
              JWTUserDetails user;
             try {
                 final Claims claims = getClaimsFromToken(token);
                 String userId = getUserIdFromToken(token);
                 String username = claims.getSubject();
                 List roles = (List) claims.get(CLAIM_KEY_AUTHORITIES);
                  Collection<? extends GrantedAuthority> authorities = parseArrayToAuthorities(roles);
                 boolean account_enabled = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_ENABLED);
                 boolean account_non_locked = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_NON_LOCKED);
                 boolean account_non_expired = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_NON_EXPIRED);
                  user = new JWTUserDetails(userId, username, "password", account_enabled, account_non_expired, true, account_non_locked, authorities);
              } catch (Exception e) {
                  user = null;
              }
             return user;
          }
         public JWTUserDetails getUserFromToken(Claims claims) {
              JWTUserDetails user;
             try {
                 //final Claims claims = getClaimsFromToken(token);
                 String userId = claims.get(CLAIM_KEY_USER_ID).toString();//getUserIdFromToken(token);
                 String username = claims.get(CLAIM_KEY_USER_ID).toString();//claims.getSubject();
                 List roles = (List) claims.get(CLAIM_KEY_AUTHORITIES);
                  Collection<? extends GrantedAuthority> authorities = parseArrayToAuthorities(roles);
                 boolean account_enabled = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_ENABLED);
                 boolean account_non_locked = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_NON_LOCKED);
                 boolean account_non_expired = (Boolean) claims.get(CLAIM_KEY_ACCOUNT_NON_EXPIRED);
                  user = new JWTUserDetails(userId, username, "password", account_enabled, account_non_expired, true, account_non_locked, authorities);
              } catch (Exception e) {
                  user = null;
              }
             return user;
          }
         public String getUserIdFromToken(String token) {
          	String userId;
             try {
                 final Claims claims = getClaimsFromToken(token);
                  userId = claims.get(CLAIM_KEY_USER_ID).toString();
              } catch (Exception e) {
                  userId = "";
              }
             return userId;
          }
         public String getUsernameFromToken(String token) {
              String username;
             try {
                 final Claims claims = getClaimsFromToken(token);
                  username = claims.get(CLAIM_KEY_USER_ID).toString();
              } catch (Exception e) {
                  username = null;
              }
             return username;
          }
         public Date getCreatedDateFromToken(String token) {
              Date created;
             try {
                 final Claims claims = getClaimsFromToken(token);
                  created = claims.getIssuedAt();
              } catch (Exception e) {
                  created = null;
              }
             return created;
          }
         public Date getExpirationDateFromToken(String token) {
              Date expiration;
             try {
                 final Claims claims = getClaimsFromToken(token);
                  expiration = claims.getExpiration();
              } catch (Exception e) {
                  expiration = null;
              }
             return expiration;
          }
         private Claims getClaimsFromToken(String token) {
              Claims claims;
             try {
                  claims = Jwts.parser()
                          .setSigningKey(secret)
                          .parseClaimsJws(token)
                          .getBody();
              } catch (Exception e) {
                  claims = null;
              }
             return claims;
          }
         private Date generateExpirationDate(long expiration) {
             return new Date(System.currentTimeMillis() + expiration * 1000);
          }
         private Boolean isTokenExpired(String token) {
             final Date expiration = getExpirationDateFromToken(token);
             return expiration.before(new Date());
          }
         private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
             return (lastPasswordReset != null && created.before(lastPasswordReset));
          }
         public String generateAccessToken(UserDetails userDetails) {
             JWTUserDetails user = (JWTUserDetails) userDetails;
              Map<String, Object> claims = generateClaims(user);
              claims.put(CLAIM_KEY_AUTHORITIES, JSON.toJSON(authoritiesToArray(user.getAuthorities())));
             return generateAccessToken(user.getUsername(), claims);
          }
         public Map<String, Object> generateAccessTokenToMap(UserDetails userDetails) {
             JWTUserDetails user = (JWTUserDetails) userDetails;
              Map<String, Object> claims = generateClaims(user);
              claims.put(CLAIM_KEY_AUTHORITIES, JSON.toJSON(authoritiesToArray(user.getAuthorities())));
             return claims;
          }
         private Map<String, Object> generateClaims(JWTUserDetails user) {
              Map<String, Object> claims = new HashMap<>();
              claims.put(CLAIM_KEY_USER_ID, user.getUserId());
              claims.put(CLAIM_KEY_ACCOUNT_ENABLED, user.isEnabled());
              claims.put(CLAIM_KEY_ACCOUNT_NON_LOCKED, user.isAccountNonLocked());
              claims.put(CLAIM_KEY_ACCOUNT_NON_EXPIRED, user.isAccountNonExpired());
             return claims;
          }
         private String generateAccessToken(String subject, Map<String, Object> claims) {
             return generateToken(subject, claims, access_token_expiration);
          }
         private List authoritiesToArray(Collection<? extends GrantedAuthority> authorities) {
              List<String> list = new ArrayList<>();
             for (GrantedAuthority ga : authorities) {
                  list.add(ga.getAuthority());
              }
             return list;
          }
         private Collection<? extends GrantedAuthority> parseArrayToAuthorities(List roles) {
              Collection<GrantedAuthority> authorities = new ArrayList<>();
              SimpleGrantedAuthority authority;
             for (Object role : roles) {
                  authority = new SimpleGrantedAuthority(role.toString());
                  authorities.add(authority);
              }
             return authorities;
          }
         public String generateRefreshToken(UserDetails userDetails) {
             JWTUserDetails user = (JWTUserDetails) userDetails;
              Map<String, Object> claims = generateClaims(user);
             // 只授于更新 token 的权限
              String roles[] = new String[]{JWTUtils.ROLE_REFRESH_TOKEN};
              claims.put(CLAIM_KEY_AUTHORITIES, JSON.toJSON(roles));
             return generateRefreshToken(user.getUsername(), claims);
          }
         private String generateRefreshToken(String subject, Map<String, Object> claims) {
             return generateToken(subject, claims, refresh_token_expiration);
          }
         public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
             final Date created = getCreatedDateFromToken(token);
             return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
                      && (!isTokenExpired(token));
          }
         public String refreshToken(String token) {
              String refreshedToken;
             try {
                 final Claims claims = getClaimsFromToken(token);
                  refreshedToken = generateAccessToken(claims.getSubject(), claims);
              } catch (Exception e) {
                  refreshedToken = null;
              }
             return refreshedToken;
          }
         private String generateToken(String subject, Map<String, Object> claims, long expiration) {
             return Jwts.builder()
                      .setClaims(claims)
                      .setSubject(subject)
                      .setId(UUID.randomUUID().toString())
                      .setIssuedAt(new Date())
                      .setExpiration(generateExpirationDate(expiration))
                      .compressWith(CompressionCodecs.DEFLATE)
                      .signWith(SIGNATURE_ALGORITHM, secret)
                      .compact();
          }
         public Boolean validateToken(String token, UserDetails userDetails) {
             JWTUserDetails user = (JWTUserDetails) userDetails;
             final String userId = getUserIdFromToken(token);
             final String username = getUsernameFromToken(token);
             // final Date created = getCreatedDateFromToken(token);
             // final Date expiration = getExpirationDateFromToken(token);
             return (userId.equals(user.getUserId())
                      && username.equals(user.getUsername())
                      && !isTokenExpired(token)
                     /* && !isCreatedBeforeLastPasswordReset(created, userDetails.getLastPasswordResetDate()) */
              );
          }
      }
  
 

      package com.yf.gyy.OAuthController;
      import java.util.ArrayList;
      import java.util.Calendar;
      import java.util.Date;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.stream.Collectors;
      import org.springframework.security.core.GrantedAuthority;
      import org.springframework.security.core.authority.SimpleGrantedAuthority;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import com.yf.gyy.OAuthConfig.JWTUserDetails;
      import com.yf.gyy.OAuthConfig.JWTUtils;
      import io.jsonwebtoken.Claims;
      import io.jsonwebtoken.Jwts;
      import io.jsonwebtoken.SignatureAlgorithm;
      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiOperation;
      @RestController
      @Api(value="OAuth2测试")
      public class OAuthController2 {
     	@ApiOperation(value="测试获取token",httpMethod="POST")
     	@RequestMapping("/api/testOAuth2/GetToken")
     	public String CreateToken()
      	{
      		List<String> roles = new ArrayList<String>();
          	roles.add("USER");
          	roles.add("ADMIN");
     		JWTUserDetails user = new JWTUserDetails("zzz",
     				"zzz",
     				"zzz",
      				mapToGrantedAuthorities(roles));
     		JWTUtils jwtUtils = new JWTUtils();
      		Map<String, Object> claims = jwtUtils.generateAccessTokenToMap(user);
         	String token = Jwts.builder()
      	            .setClaims(claims)
      	            .setExpiration(new Date(System.currentTimeMillis() + 6000 * 1000))
      	            .signWith(SignatureAlgorithm.HS512,"123456") //采用什么算法是可以自己选择的,不一定非要采用HS512
      	            .compact();
     		return token;
      	}
     	private  List<GrantedAuthority> mapToGrantedAuthorities(List<String> authorities) {
             return authorities.stream()
                      .map(SimpleGrantedAuthority::new)
                      .collect(Collectors.toList());
          }
     	@ApiOperation(value="测试token解析",httpMethod="POST")
     	@RequestMapping("/api/testOAuth2/TestOAuth2")
     	public Claims TestOAuth2( @RequestBody String token)
      	{
      		System.out.println(token);
     		Claims  claims = Jwts.parser()
                      .setSigningKey("123456")
                      .parseClaimsJws(token)
                      .getBody();
     		return claims;
      	}
      }
  
 

    


      package com.yf.gyy.OAuthController;
      import org.springframework.security.access.prepost.PreAuthorize;
      import org.springframework.security.core.context.SecurityContextHolder;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import com.yf.gyy.OAuthConfig.JWTUserDetails;
      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiOperation;
      @RestController
      @Api(value="OAuth2测试")
      //@PreAuthorize("hasRole('ROLE_USER')") //判断角色
      @PreAuthorize("authenticated")
      //@PreAuthorize("principal.username!=null") //用户名不为空
      public class OAuthController {
     	@ApiOperation(value="测试访问授权",httpMethod="POST")
     	@RequestMapping("/api/testOAuth/TestAccessToken")
     	public String TestAccessToken()
      	{
     		JWTUserDetails userDetails = (JWTUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
     		String userid = userDetails.getUserId();
     		return "test oauth" + userid;
      	}
      }
  
 

生成token接口:http://127.0.0.1:8080/api/testOAuth2/GetToken


授权访问接口:http://127.0.0.1:8080/api/testOAuth/TestAccessToken


文章来源: zzzili.blog.csdn.net,作者:清雨小竹,版权归原作者所有,如需转载,请联系作者。

原文链接:zzzili.blog.csdn.net/article/details/79398803

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。