Sprint Boot使用OAuth和JWT实现身份认证【二】
【摘要】
上一篇文章已经实现了自定义获取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)