授权拦截
This commit is contained in:
parent
ef5d90621f
commit
5009482aac
|
|
@ -1,111 +0,0 @@
|
||||||
package com.hxkj.admin.config;
|
|
||||||
|
|
||||||
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
|
||||||
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
|
||||||
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
|
||||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
|
||||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class ShiroConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安全管理器
|
|
||||||
*
|
|
||||||
* @param realmConfig realmConfig
|
|
||||||
* @return DefaultWebSecurityManager
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public DefaultWebSecurityManager doDefaultWebSecurityManager(ShiroRealm realmConfig) {
|
|
||||||
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
|
|
||||||
defaultWebSecurityManager.setRealm(realmConfig);
|
|
||||||
|
|
||||||
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
|
|
||||||
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
|
|
||||||
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
|
|
||||||
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
|
|
||||||
defaultWebSecurityManager.setSubjectDAO(subjectDAO);
|
|
||||||
|
|
||||||
return defaultWebSecurityManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截过滤器配置
|
|
||||||
* anon: 无需认证就可以访问
|
|
||||||
* authc: 必须认证了才能访问
|
|
||||||
* perms: 拥有某个资源权限才能访问
|
|
||||||
* role: 拥有某个角色权限才能访问
|
|
||||||
* @return ShiroFilterFactoryBean
|
|
||||||
*/
|
|
||||||
@Bean(name = "shiroFilter")
|
|
||||||
public ShiroFilterFactoryBean doShiroFactoryFilterBean(DefaultWebSecurityManager defaultWebSecurityManager) {
|
|
||||||
// 设置安全管理器
|
|
||||||
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
|
|
||||||
bean.setSecurityManager(defaultWebSecurityManager);
|
|
||||||
|
|
||||||
// 设置内置过滤器
|
|
||||||
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
|
|
||||||
filterChainDefinitionMap .put("/user/add", "authc");
|
|
||||||
filterChainDefinitionMap .put("/user/update", "authc");
|
|
||||||
bean.setFilterChainDefinitionMap(filterChainDefinitionMap );
|
|
||||||
|
|
||||||
// 设置自定过滤器
|
|
||||||
LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>();
|
|
||||||
filterMap.put("jwt", jwtFilter());
|
|
||||||
bean.setFilters(filterMap);
|
|
||||||
|
|
||||||
// 返回构建配置
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SpringShiroFilter首先注册到spring容器
|
|
||||||
* 然后被包装成FilterRegistrationBean
|
|
||||||
* 最后通过FilterRegistrationBean注册到servlet容器
|
|
||||||
*
|
|
||||||
* @return FilterRegistrationBean
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public FilterRegistrationBean<DelegatingFilterProxy> delegatingFilterProxy(){
|
|
||||||
FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean = new FilterRegistrationBean<>();
|
|
||||||
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
|
|
||||||
proxy.setTargetFilterLifecycle(true);
|
|
||||||
proxy.setTargetBeanName("shiroFilter");
|
|
||||||
filterRegistrationBean.setFilter(proxy);
|
|
||||||
return filterRegistrationBean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置加密次数
|
|
||||||
*
|
|
||||||
* @return HashedCredentialsMatcher
|
|
||||||
*/
|
|
||||||
@Bean(name = "hashedCredentialsMatcher")
|
|
||||||
public HashedCredentialsMatcher hashedCredentialsMatcher() {
|
|
||||||
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
|
|
||||||
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
|
|
||||||
hashedCredentialsMatcher.setHashIterations(1024);// 设置加密次数
|
|
||||||
return hashedCredentialsMatcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 自定realm
|
|
||||||
@Bean
|
|
||||||
public ShiroRealm userRealm() {
|
|
||||||
return new ShiroRealm();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public JwtFilter jwtFilter() {
|
|
||||||
return new JwtFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package com.hxkj.admin.config;
|
|
||||||
|
|
||||||
import com.hxkj.admin.service.ISysAdminService;
|
|
||||||
import com.hxkj.common.entity.system.SysAdmin;
|
|
||||||
import org.apache.catalina.User;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
|
||||||
import org.apache.shiro.authc.*;
|
|
||||||
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.apache.shiro.subject.Subject;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ShiroRealm extends AuthorizingRealm {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
ISysAdminService iSysAdminService;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(AuthenticationToken token) {
|
|
||||||
return token instanceof JwtToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 授权: 根据认证数据验证用户权限
|
|
||||||
*
|
|
||||||
* @param principals 包含了所有已认证的安全数据
|
|
||||||
* @return AuthorizationInfo 授权数据
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
|
||||||
// 1、获取用户安全数据
|
|
||||||
Integer adminId = (Integer) principals.getPrimaryPrincipal();
|
|
||||||
|
|
||||||
// 2、根据用户ID查询用户
|
|
||||||
|
|
||||||
// 3、查询用户角色权限
|
|
||||||
List<String> perms = new ArrayList<>();
|
|
||||||
perms.add("user:add");
|
|
||||||
perms.add("user:update");
|
|
||||||
|
|
||||||
List<String> roles = new ArrayList<>();
|
|
||||||
roles.add("role1");
|
|
||||||
roles.add("role2");
|
|
||||||
|
|
||||||
// 4、构造返回
|
|
||||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
|
||||||
info.addStringPermissions(perms);
|
|
||||||
info.addRoles(roles);
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 认证: 校验用户名和密码是否一致
|
|
||||||
*
|
|
||||||
* @param auth 令牌
|
|
||||||
* @return AuthenticationInfo
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) {
|
|
||||||
|
|
||||||
System.out.println("靠靠靠靠靠靠靠");
|
|
||||||
String token = (String) auth.getCredentials();
|
|
||||||
|
|
||||||
// 登录参数
|
|
||||||
// UsernamePasswordToken upToken = (UsernamePasswordToken) token;
|
|
||||||
// String username = upToken.getUsername();
|
|
||||||
// String password = new String(upToken.getPassword());
|
|
||||||
//
|
|
||||||
// // 验证用户
|
|
||||||
// SysAdmin sysAdmin = iSysAdminService.findByUsername(username);
|
|
||||||
// if (sysAdmin == null) {
|
|
||||||
// return null;
|
|
||||||
// } else if (!password.equals(sysAdmin.getPassword())) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 登录成功
|
|
||||||
return new SimpleAuthenticationInfo(1, "13", "shiroRealm");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.hxkj.admin.config;
|
package com.hxkj.admin.config.shiro;
|
||||||
|
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
@ -12,64 +11,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public class JwtFilter extends BasicHttpAuthenticationFilter {
|
public class JwtFilter extends BasicHttpAuthenticationFilter {
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行登录认证(判断请求头是否带上token)
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param mappedValue
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
|
||||||
System.out.println("酷酷酷酷酷");
|
|
||||||
// 如果请求头不存在token,则可能是执行登陆操作或是游客状态访问,直接返回true
|
|
||||||
if (isLoginAttempt(request, response)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果存在,则进入executeLogin方法执行登入,检查token 是否正确
|
|
||||||
try {
|
|
||||||
executeLogin(request, response);return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AuthenticationException("Token失效请重新登录");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断用户是否是登入,检测headers里是否包含token字段
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
|
|
||||||
|
|
||||||
HttpServletRequest req = (HttpServletRequest) request;
|
|
||||||
// if(antPathMatcher.match("/userLogin",req.getRequestURI())){
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// String token = req.getHeader("token");
|
|
||||||
// if (token == null) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// Object o = redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token);
|
|
||||||
// if(ObjectUtils.isEmpty(o)){
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重写AuthenticatingFilter的executeLogin方法丶执行登陆操作
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
|
|
||||||
|
|
||||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
|
||||||
String token = httpServletRequest.getHeader("token");//Access-Token
|
|
||||||
JwtToken jwtToken = new JwtToken(token);
|
|
||||||
// 提交给realm进行登入,如果错误他会抛出异常并被捕获, 反之则代表登入成功,返回true
|
|
||||||
getSubject(request, response).login(jwtToken);return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对跨域提供支持
|
* 对跨域提供支持
|
||||||
*/
|
*/
|
||||||
|
|
@ -87,4 +28,56 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
|
||||||
return super.preHandle(request, response);
|
return super.preHandle(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断用户是否想要登入。
|
||||||
|
* 检测header里面是否包含Authorization字段即可
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
String authorization = req.getHeader("Authorization");
|
||||||
|
return authorization != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行登录认证
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||||
|
if (isLoginAttempt(request, response)) {
|
||||||
|
try {
|
||||||
|
executeLogin(request, response);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.responseUnAuth(response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将非法请求跳转到 401
|
||||||
|
*/
|
||||||
|
private void responseUnAuth(ServletResponse resp) {
|
||||||
|
try {
|
||||||
|
HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
|
||||||
|
httpServletResponse.sendRedirect("/user/unauthorized");
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤器,每次登陆的时候,都从Header的Authorization,
|
||||||
|
* 获取到token,然后执行登陆的操作
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean executeLogin(ServletRequest request, ServletResponse response) {
|
||||||
|
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||||
|
String token = httpServletRequest.getHeader("Authorization");
|
||||||
|
JwtToken jwtToken = new JwtToken(token);
|
||||||
|
getSubject(request, response).login(jwtToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.hxkj.admin.config;
|
package com.hxkj.admin.config.shiro;
|
||||||
|
|
||||||
import org.apache.shiro.authc.AuthenticationToken;
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
|
||||||
|
|
@ -8,18 +8,37 @@ import org.apache.shiro.authc.AuthenticationToken;
|
||||||
*/
|
*/
|
||||||
public class JwtToken implements AuthenticationToken {
|
public class JwtToken implements AuthenticationToken {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌
|
||||||
|
*/
|
||||||
private final String token;
|
private final String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
*/
|
||||||
public JwtToken(String token) {
|
public JwtToken(String token) {
|
||||||
System.out.println("就将计就计");
|
super();
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Token
|
||||||
|
*/
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取账号
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object getPrincipal() {
|
public Object getPrincipal() {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取密码
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return token;
|
return token;
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package com.hxkj.admin.config.shiro;
|
||||||
|
|
||||||
|
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
||||||
|
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
|
||||||
|
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
||||||
|
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
||||||
|
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||||
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||||
|
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||||
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||||
|
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ShiroConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤器注册
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<Filter> doFilterRegistrationBean() {
|
||||||
|
FilterRegistrationBean<Filter> filterRegistration = new FilterRegistrationBean<>();
|
||||||
|
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
|
||||||
|
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
|
||||||
|
filterRegistration.setEnabled(true);
|
||||||
|
filterRegistration.addUrlPatterns("/");
|
||||||
|
return filterRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期对象
|
||||||
|
*/
|
||||||
|
@Bean(name = "lifecycleBeanPostProcessor")
|
||||||
|
public LifecycleBeanPostProcessor doLifecycleBeanPostProcessor() {
|
||||||
|
return new LifecycleBeanPostProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加注解支持
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DefaultAdvisorAutoProxyCreator doDefaultAdvisorAutoProxyCreator() {
|
||||||
|
// // 强制使用cglib,防止重复代理和可能引起代理出错的问题
|
||||||
|
DefaultAdvisorAutoProxyCreator dap = new DefaultAdvisorAutoProxyCreator();
|
||||||
|
dap.setProxyTargetClass(true);
|
||||||
|
return dap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定realm
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public ShiroRealm shiroRealm() {
|
||||||
|
return new ShiroRealm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全管理器
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DefaultWebSecurityManager doDefaultWebSecurityManager() {
|
||||||
|
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||||
|
securityManager.setRealm(this.shiroRealm());
|
||||||
|
securityManager.setCacheManager(new MemoryConstrainedCacheManager());
|
||||||
|
|
||||||
|
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
|
||||||
|
DefaultSessionStorageEvaluator evaluator = new DefaultSessionStorageEvaluator();
|
||||||
|
evaluator.setSessionStorageEnabled(false);
|
||||||
|
subjectDAO.setSessionStorageEvaluator(evaluator);
|
||||||
|
securityManager.setSubjectDAO(subjectDAO);
|
||||||
|
return securityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限源切面
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public AuthorizationAttributeSourceAdvisor doAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
|
||||||
|
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
|
||||||
|
advisor.setSecurityManager(securityManager);
|
||||||
|
return advisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截过滤器配置
|
||||||
|
* anon: 无需认证就可以访问
|
||||||
|
* authc: 必须认证了才能访问
|
||||||
|
* perms: 拥有某个资源权限才能访问
|
||||||
|
* role: 拥有某个角色权限才能访问
|
||||||
|
* @return ShiroFilterFactoryBean
|
||||||
|
*/
|
||||||
|
@Bean(name = "shiroFilter")
|
||||||
|
public ShiroFilterFactoryBean doShiroFactoryFilterBean(DefaultWebSecurityManager securityManager) {
|
||||||
|
// 设定认证管理
|
||||||
|
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
|
||||||
|
bean.setSecurityManager(securityManager);
|
||||||
|
|
||||||
|
// 添加自定过滤器
|
||||||
|
Map<String, Filter> filterMap = new LinkedHashMap<>();
|
||||||
|
filterMap.put("jwt", new JwtFilter());
|
||||||
|
bean.setFilters(filterMap);
|
||||||
|
|
||||||
|
// 添加授权链接
|
||||||
|
Map<String,String> chainMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
chainMap.put("/user/add", "authc");
|
||||||
|
// chainMap.put("/user/update", "jwt");
|
||||||
|
chainMap.put("/user/login", "anon");
|
||||||
|
chainMap.put("/**", "jwt");
|
||||||
|
bean.setFilterChainDefinitionMap(chainMap);
|
||||||
|
|
||||||
|
// 返回构建配置
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.hxkj.admin.config.shiro;
|
||||||
|
|
||||||
|
import com.hxkj.admin.service.ISysAdminService;
|
||||||
|
import com.hxkj.common.utils.JwtUtil;
|
||||||
|
import org.apache.shiro.authc.*;
|
||||||
|
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 javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ShiroRealm extends AuthorizingRealm {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
ISysAdminService iSysAdminService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写判断token是否是JwtToke
|
||||||
|
*
|
||||||
|
* @param token AuthenticationToken
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supports(AuthenticationToken token) {
|
||||||
|
return token instanceof JwtToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权: 根据认证数据验证用户权限
|
||||||
|
*
|
||||||
|
* @param principals 包含了所有已认证的安全数据
|
||||||
|
* @return AuthorizationInfo 授权数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
||||||
|
System.out.println("————权限认证————");
|
||||||
|
|
||||||
|
Set<String> perms = new HashSet<>();
|
||||||
|
Set<String> roles = new HashSet<>();
|
||||||
|
|
||||||
|
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||||
|
info.addStringPermissions(perms);
|
||||||
|
info.addRoles(roles);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证: 校验用户名和密码是否一致
|
||||||
|
*
|
||||||
|
* @param authenticationToken token
|
||||||
|
* @return AuthenticationInfo
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
|
||||||
|
JwtToken jwtToken = (JwtToken) authenticationToken;
|
||||||
|
|
||||||
|
String token = jwtToken.getToken();
|
||||||
|
Integer userId = JwtUtil.getAudience(token);
|
||||||
|
|
||||||
|
if (userId == null || userId <= 0) {
|
||||||
|
throw new AuthenticationException("用户异常");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SimpleAuthenticationInfo(token, token, "shiroRealm");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
package com.hxkj.admin.controller.system;
|
package com.hxkj.admin.controller.system;
|
||||||
|
|
||||||
|
import com.hxkj.admin.config.shiro.JwtToken;
|
||||||
|
import com.hxkj.admin.service.ISysAdminService;
|
||||||
import com.hxkj.admin.validate.SysLoginParam;
|
import com.hxkj.admin.validate.SysLoginParam;
|
||||||
import com.hxkj.common.core.AjaxResult;
|
import com.hxkj.common.core.AjaxResult;
|
||||||
|
import com.hxkj.common.entity.system.SysAdmin;
|
||||||
import com.hxkj.common.utils.JwtUtil;
|
import com.hxkj.common.utils.JwtUtil;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
import org.apache.shiro.authc.IncorrectCredentialsException;
|
|
||||||
import org.apache.shiro.authc.UnknownAccountException;
|
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -15,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -22,6 +22,9 @@ import java.util.Map;
|
||||||
@RequestMapping("/api/system")
|
@RequestMapping("/api/system")
|
||||||
public class SysLoginController {
|
public class SysLoginController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
ISysAdminService iSysAdminService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录系统
|
* 登录系统
|
||||||
*
|
*
|
||||||
|
|
@ -31,23 +34,24 @@ public class SysLoginController {
|
||||||
*/
|
*/
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public Object login(@Validated() @RequestBody SysLoginParam sysLoginParam) {
|
public Object login(@Validated() @RequestBody SysLoginParam sysLoginParam) {
|
||||||
|
|
||||||
|
|
||||||
String username = sysLoginParam.getUsername();
|
String username = sysLoginParam.getUsername();
|
||||||
String password = sysLoginParam.getPassword();
|
String password = sysLoginParam.getPassword();
|
||||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
|
|
||||||
System.out.println("斤斤计较");
|
// 查询用户
|
||||||
Subject subject = SecurityUtils.getSubject();
|
SysAdmin sysAdmin = iSysAdminService.findByUsername(username);
|
||||||
try {
|
if (sysAdmin == null || sysAdmin.getIsDelete() == 1) {
|
||||||
subject.login(token);
|
return AjaxResult.failed("账号或密码错误");
|
||||||
return AjaxResult.success();
|
|
||||||
} catch (AuthenticationException e) {
|
|
||||||
String msg = "用户或密码错误";
|
|
||||||
if (!e.getMessage().equals("")) {
|
|
||||||
msg = e.getMessage();
|
|
||||||
}
|
|
||||||
return AjaxResult.failed(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成令牌
|
||||||
|
String tokenStr = JwtUtil.createToken(sysAdmin.getId());
|
||||||
|
JwtToken token = new JwtToken(tokenStr);
|
||||||
|
|
||||||
|
// 登录用户
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
subject.login(token);
|
||||||
|
|
||||||
|
return AjaxResult.success("登录成功", tokenStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ spring:
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
mapper-locations: classpath*:/mapper/**Mapper.xml # 映射文件路径
|
mapper-locations: classpath*:/mapper/**Mapper.xml # 映射文件路径
|
||||||
typeAliasesPackage: com.hxkj.**.mapper
|
typeAliasesPackage: com.hxkj.**.mapper
|
||||||
configuration:
|
# configuration:
|
||||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
global-config:
|
global-config:
|
||||||
banner: false
|
banner: false
|
||||||
db-config:
|
db-config:
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,18 @@ public class AjaxResult {
|
||||||
return new AjaxResult(code, msg, new ArrayList<>());
|
return new AjaxResult(code, msg, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功返回结果
|
||||||
|
*
|
||||||
|
* @author fzr
|
||||||
|
* @param msg 提示信息
|
||||||
|
* @param data 响应数据
|
||||||
|
* @return AjaxResult
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(String msg, Object data) {
|
||||||
|
return new AjaxResult(HttpEnum.SUCCESS.getCode(), msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成功返回结果
|
* 成功返回结果
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ package com.hxkj.common.utils;
|
||||||
import com.auth0.jwt.JWT;
|
import com.auth0.jwt.JWT;
|
||||||
import com.auth0.jwt.JWTCreator;
|
import com.auth0.jwt.JWTCreator;
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||||
|
import com.auth0.jwt.interfaces.Claim;
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -33,36 +36,59 @@ public class JwtUtil {
|
||||||
* 创建token
|
* 创建token
|
||||||
*
|
*
|
||||||
* @author fzr
|
* @author fzr
|
||||||
* @param map 参数
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
public static String createToken(Map<String, String> map) {
|
public static String createToken(Integer userId) {
|
||||||
Calendar instance = Calendar.getInstance();
|
Calendar instance = Calendar.getInstance();
|
||||||
instance.add(Calendar.SECOND, expire);
|
instance.add(Calendar.SECOND, expire);
|
||||||
|
|
||||||
JWTCreator.Builder builder = JWT.create();
|
return JWT.create()
|
||||||
map.forEach(builder::withClaim);
|
.withAudience(String.valueOf(userId)) // 签发对象
|
||||||
return builder.withExpiresAt(instance.getTime())
|
.withIssuedAt(new Date()) // 发行时间
|
||||||
.withIssuedAt(new Date())
|
.withExpiresAt(instance.getTime()) // 有效时间
|
||||||
.sign(Algorithm.HMAC256(secret));
|
.withClaim("userId", userId) // 载荷
|
||||||
|
.sign(Algorithm.HMAC256(secret)); // 加密
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token是否过期
|
* 检验合法性
|
||||||
* @author fzr
|
*
|
||||||
* @param token token
|
* @param token 令牌
|
||||||
*/
|
*/
|
||||||
public void isTokenExpired(String token) {
|
public static void verifyToken(String token) {
|
||||||
JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
|
try {
|
||||||
|
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
|
||||||
|
verifier.verify(token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取token中的payload
|
* 获取签发对象
|
||||||
* @author fzr
|
*
|
||||||
* @param token token
|
* @param token 令牌
|
||||||
* @return DecodedJWT
|
* @return userId
|
||||||
*/
|
*/
|
||||||
public static DecodedJWT getToken(String token) {
|
public static Integer getAudience(String token) {
|
||||||
return JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
|
Integer audience = null;
|
||||||
|
try {
|
||||||
|
audience = Integer.parseInt(JWT.decode(token).getAudience().get(0));
|
||||||
|
} catch (JWTDecodeException j) {
|
||||||
|
System.out.println(j.getMessage());
|
||||||
|
}
|
||||||
|
return audience;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过载荷名字获取载荷的值
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
* @param name 载荷名称
|
||||||
|
* @return Claim
|
||||||
|
*/
|
||||||
|
public static Claim getClaimByName(String token, String name){
|
||||||
|
return JWT.decode(token).getClaim(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue