springboot 2 + shiro + jwt 통합 (1) 로그 인 인증
18587 단어 springboot권한
왜 JWT 를 사용 합 니까?
1. 간결 함 (컴 팩 트): URL, POST 인자 또는 HTTP header 를 통 해 보 낼 수 있 습 니 다. 데이터 양 이 적 고 전송 속도 도 빠 르 기 때 문 입 니 다.
2. 자체 포함 (Self - contained): 부하 에는 모든 사용자 가 필요 로 하 는 정보 가 포함 되 어 있어 여러 번 데이터 베 이 스 를 조회 하지 않 습 니 다.
3. 보안 (security): 간단 한 JSON 에 비해 XML 과 XML 디지털 서명 회 는 복잡 한 보안 구멍 을 도입 합 니 다.
인증 원리
1. 사용자 가 로그 인 한 후 비밀 번 호 를 사용 하여 계 정 에 서명 하고 token 으로 돌아 가 만 료 시간 을 설정 합 니 다.
2. token 을 로 컬 에 저장 하고 요청 을 보 낼 때마다 header 에 token 을 휴대 합 니 다.
3. shiro 필 터 는 요청 을 차단 하고 header 의 token 을 가 져 오 며 사용자 정의 realm 의 doGetAuthenticationInfo 방법 에 제출 합 니 다.
4. jwt 디 코딩 을 통 해 token 의 사용자 이름 을 가 져 오고 데이터베이스 에서 비밀 번 호 를 조회 한 후 비밀번호 에 따라 jwt 효과 기 를 생 성하 고 token 을 검증한다.
OK, 소개 하고 코드 올 려 주세요.
JWT
pom 도입
com.auth0
java-jwt
3.4.0
우선 token 을 포장 할 대상 을 사용자 정의 해 야 합 니 다.
JwtToken
package com.style.orange.shiro;
import org.apache.shiro.authc.AuthenticationToken;
/**
* @author Mr.Li
* @create 2018-07-12 15:19
* @desc
**/
public class JwtToken implements AuthenticationToken {
private String token;
public JwtToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}
서명 과 효 과 를 위 한 도구 클래스 를 하나 더 작성 합 니 다 Token
JwtToken
package com.style.orange.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
/**
* @author Mr.Li
* @create 2018-07-12 14:23
* @desc JWT
**/
public class JwtUtil {
private static final long EXPIRE_TIME = 5 * 60 * 1000;
/**
* token
*
* @param token
* @param secret
* @return
*/
public static boolean verify(String token, String username, String secret) {
try {
// JWT
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
// TOKEN
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/**
* token secret
*
* @return token
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* ,5min
*
* @param username
* @param secret
* @return token
*/
public static String sign(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// username
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date)
.sign(algorithm);
}
}
앞에서 인증 원 리 는 우리 가 shiro 를 사용 하여 token 을 차단 하려 면 jwt 필 터 를 써 서 shiro 의 필터 로 해 야 한다 고 말 했다.
JwtFilter
import com.style.orange.shiro.JwtToken;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Mr.Li
* @create 2018-07-12 15:56
* @desc
**/
public class JwtFilter extends BasicHttpAuthenticationFilter {
/**
*
*
* @param request
* @param response
* @param mappedValue
* @return
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
try {
executeLogin(request, response);
return true;
} catch (Exception e) {
return false;
}
}
/**
*
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("Authorization");
JwtToken jwtToken = new JwtToken(token);
// realm ,
getSubject(request, response).login(jwtToken);
// , true
return true;
}
/**
*
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
// option , option
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
}
Shiro
pom 도입
org.apache.shiro
shiro-spring
1.4.0
사용자 정의 Realm 준비
MyRealm
package com.style.orange.shiro;
import com.style.orange.model.SysUser;
import com.style.orange.service.SysUserService;
import com.style.orange.utils.JwtUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author Mr.Li
* @create 2018-07-12 15:23
* @desc
**/
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
private SysUserService sysUserService;
/**
* , Shiro
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
* , checkRole,checkPermission
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = JwtUtil.getUsername(principals.toString());
SysUser user = sysUserService.findByUserName(username);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
return simpleAuthorizationInfo;
}
/**
* , 。
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
// username,
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token ");
}
SysUser userBean = sysUserService.findByUserName(username);
if (userBean == null) {
throw new AuthenticationException(" !");
}
if (!JwtUtil.verify(token, username, userBean.getPassword())) {
throw new AuthenticationException(" ");
}
return new SimpleAuthenticationInfo(token, token, "my_realm");
}
}
ShiroConfig
package com.style.orange.shiro;
import com.style.orange.filter.JwtFilter;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author: PENG
* @date: 2018/2/7
* @description: shiro
*/
@Configuration
public class ShiroConfig {
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//
Map filterChainDefinitionMap = new LinkedHashMap();
//
filterChainDefinitionMap.put("/login/**", "anon");
filterChainDefinitionMap.put("/**.js", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/swagger**/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
// jwt
Map filterMap = new HashMap(1);
filterMap.put("jwt", new JwtFilter());
shiroFilterFactoryBean.setFilters(filterMap);
//
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin Springboot -- 파트 14 사용 사례 REST로 전환하여 POST로 JSON으로 전환前回 前回 前回 記事 の は は で で で で で で を 使っ 使っ 使っ て て て て て リクエスト を を 受け取り 、 reqeustbody で 、 その リクエスト の ボディ ボディ を を 受け取り 、 関数 内部 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.