代码拉取完成,页面将自动刷新
tip:这是一个通用模板框架 可以适用于 前后端不分离 或者 前后端不分离 就算不是分布式下依旧可以,但是没必要.
2019/2/27 更新:重写shiro未授权或未登入的跳转方式 具体看step5
@Configuration
@Slf4j
public class APPShiroConfig {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterMap = new LinkedHashMap();
filterMap.put("111111111111111111111/shiro/mp/login", "anon");
filterMap.put("22222222222222222222/**", "authc");
log.info("当前系统拦截模式为:{}", filterMap);
shiroFilterFactoryBean.setUnauthorizedUrl("33333333333/admin/page/noAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setLoginUrl("4444444444444444444/shiro/mp/nologinCode");
return shiroFilterFactoryBean;
}
}
@Component
@Slf4j
public class ShiroUserDetailServiceImpl implements ShiroUserDetailService {
@Autowired
private CompanyProperties companyProperties;
@Autowired
private MpUserInfoMapper mpUserInfoMapper;
@Autowired
private MpSocialInfoMapper mpSocialInfoMapper;
@Autowired
private MpShiroPermsInfoMapper mpShiroPermsInfoMapper;
@Override
public ShiroUserDetail getByMobile(String mobile) throws AuthenticationException {
MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("mobile", mobile));
if (PublicUtil.isEmpty(mpUserInfo)) {
log.error("未找到与该手机号相关联的用户 :mobile=[ {} ]", mobile);
throw new AccountException("未找到与该手机号相关联的用户");
}
return this.filling(mpUserInfo);
}
@Override
public ShiroUserDetail getByUserName(String username) throws AuthenticationException {
MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("username", username));
if (PublicUtil.isEmpty(mpUserInfo)) {
log.error("未找到该用户名对应的用户 :username=[ {} ]", username);
throw new AccountException("未找到该用户名对应的用户");
}
return this.filling(mpUserInfo);
}
@Override
public ShiroUserDetail getBySocialProvider(String itemId, String socialProviderId) throws AuthenticationException {
String[] split = socialProviderId.split(":" + companyProperties.getLoginSplit() + ":");
if (split.length!=2) {
throw new PrefixNotFoundException("社交登入,没有分隔符");
}
String social = split[0]; // openId/unionId
String socialUnderLine = PublicUtil.underline(new StringBuffer(social)).toString();
String providerId = split[1]; //wx/qq
log.warn("社交登入中的: social= [ {} 登入,主体为 {} ],providerId=[ {} ]", social,itemId, providerId);
List<MpSocialInfo> mpSocialInfos = mpSocialInfoMapper.selectList(
new QueryWrapper<MpSocialInfo>().eq(socialUnderLine, itemId).eq("provider_id", providerId));
if (PublicUtil.isEmpty(mpSocialInfos)) {
log.error("未找到社交登入的账号 :social=[ {} ],providerId=[ {} ]", social, providerId);
throw new SocialUserNotFoundException("未找到对应的社交登入记录");
}
long userId = Long.parseLong(mpSocialInfos.iterator().next().getUserId());
MpUserInfo mpUserInfo = mpUserInfoMapper.selectById(userId);
return this.filling(mpUserInfo);
}
private ShiroUserDetail filling(MpUserInfo mpUserInfo) throws AuthenticationException {
List<MpShiroPermsInfo> mpShiroPermsInfos = mpShiroPermsInfoMapper.selectList(new QueryWrapper<MpShiroPermsInfo>().eq("user_id", mpUserInfo.getId()));
List<String> perms = Lists.newArrayList();
if (PublicUtil.isNotEmpty(mpShiroPermsInfos)) {
mpShiroPermsInfos.forEach(obj -> perms.add(obj.getPerms()));
mpUserInfo.setPerms(perms);
mpUserInfo.setMpShiroPermsInfoList(mpShiroPermsInfos);
}
log.warn("数据库查询成功 登入用户为 userId=[ {} ],用户名为:[ {} ]", mpUserInfo.getId().toString(), mpUserInfo.getUsername());
log.warn("shiro框架识别用户名成功 < ================= < ============== < ");
return new ShiroUserDetail(mpUserInfo.getId().toString(), mpUserInfo.getUsername(), mpUserInfo.getPassword(), mpUserInfo.getPerms());
}
}
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.4.2.1-RELEASE</version>
</dependency>
@Bean
public SessionManager sessionManager() {
//配置sessionId获取方式.这里用ajax请求头
MySessionManager mySessionManager = new MySessionManager();
//配置session获得方式 最终是SessionDAO类获取session会话.所以要重写
mySessionManager.setSessionDAO(sessionDAO());
return mySessionManager;
}
@Bean
SessionDAO sessionDAO() {
log.error("使用redis缓存");
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
log.info("设置redisSessionDAO");
return redisSessionDAO;
}
@Bean
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
redisManager.setPassword(password);
redisManager.setExpire(timeout);// 配置过期时间
log.info("配置redis连接设置##########" + host + ":::" + port);
return redisManager;
}
原本shiro未授权或未登入是在ShiroFilterFactoryBean 设置
shiroFilterFactoryBean.setUnauthorizedUrl("33333333333/admin/page/noAuth");
shiroFilterFactoryBean.setLoginUrl("4444444444444444444/shiro/mp/nologinCode");
但是这个方式是重定向方式,如果是前后端不分离也就是java控制页面控制器,并没有问题.
但是如果前后端分离之后,页面控制器权力在前端手中,我们是需要给予返回json中的code例如2000状态码判断是否登入或授权
而shiro默认跳转方式重定向,而前端get请求无法捕捉重定向方式,所以要重写以上2句代码对应的跳转方法
filter包下
=> NoLoginFilter 未登入下的直接返回状态码
saveRequestAndRedirectToLogin
=> NoPermsFilter 未权限授权下的直接返回状态码
=> NoRolesFilter 未权限授权下的直接返回状态码 未授权需要重写2个跳转,因为未授权之前要先判断是否有登入,登入之后再判断是否授权
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
Subject subject = getSubject(request, response);
if (subject.getPrincipal() == null) {
log.error("该用户在访问受角色保护资源时候未登入");
//未登入
ShiroURLFunction.saveRequestAndRedirectToLogin(request, response);
} else {
HttpServletRequest httpServletRequest= (HttpServletRequest) request;
log.error("用户:[ {} ] 没有访问该角色资源 [ {} ]",ShiroUtils.getUser().getUsername(),httpServletRequest.getRequestURI());
ShiroThreadLocalMap.put("noAuthError", new StringBuilder().append("用户:[ ")
.append(ShiroUtils.getUser().getUsername()).append(" ]")
.append("没有访问该角色资源 [ ").append(httpServletRequest.getRequestURI()).append(" ]"));
ShiroURLFunction.saveRequestAndRedirectToNoAuth(request, response);
}
return false;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型