org.apache.shiro
shiro-spring
1.4.0
org.apache.shiro
shiro-web
1.4.0
org.apache.shiro
shiro-core
1.4.0
org.springframework.boot
spring-boot-starter-log4j
1.3.8.RELEASE
mysql
mysql-connector-java
8.0.13
com.alibaba
druid-spring-boot-starter
1.1.9
javax.servlet
javax.servlet-api
4.0.1
provided
org.springframework.boot
spring-boot-devtools
true
true
org.springframework.boot
spring-boot-maven-plugin
org.springframework.boot
spring-boot-maven-plugin
true
package com.zhiyi.shiro.config;
import com.zhiyi.shiro.mapper.GetMapper;
import com.zhiyi.shiro.model.Shiro_User;
import com.zhiyi.shiro.model.Shiro_User_Role;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.LinkedList;
import java.util.List;
public class MyShiroRealm extends AuthorizingRealm {
private JdbcTemplate jdbcTemplate;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private GetMapper getMapper;
@Override
public String getName() {
return “MyShiroRealm”;
}
@Override
public boolean supports(AuthenticationToken token) {
//仅支持UsernamePasswordToken类型的Token
return token instanceof UsernamePasswordToken;
}
/**
-
用于获取登录成功后的角色、权限等信息
-
@param principals
-
@return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//先通过用户名查询角色
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
Shiro_User user=(Shiro_User) (principals.getPrimaryPrincipal());//获取当前与系统交互的对象
List roles=getMapper.getUserRolesByName(user.getUserName());//通过用户名获取该用户对应的角色
//下面用于通过角色名获取对应的权限名
for (String role:roles){
List lpermissions=getMapper.getPermissionByRoleName(role);
info.addStringPermissions(lpermissions);
}
//将查询出的结果封装在权限信息里面
info.addRoles(roles);
return info;
}
/**
-
验证当前登录的Subject
-
@param token
-
@return
-
@throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
Shiro_User user=getMapper.getShiroUserByName(username);
if (user==null){
logger.info(“数据库中不存在该用户”);
return null;
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),getName());
return info;
}
}
我大概解释一下上面的代码:
realm 可以写在配置文件中(ini 文件中)也可以自定义,一般均采用这种自定义规则,也可以同时写多个 realm,只需将你的 realm 装配到你的 securityMa
GetMapper 对应的代码以及其他代码都已存到 git 上面,大家可以在文章末尾进行下载:
2.2 接着配置 shiro 的配置类,添加监听器,与过滤器,springBoot 与普通的 springmvc 模式不同
- springMvc 下的
监听器,过滤器只需在 web.xml 文件中添加
在 springBoot 中只需添加一个配置类,在每个配置上加上@Bean 即可,何为配置类,所有的类只要加上@Configuration 就变成了一个配置类,然后再主配置类上加上两个注解:
@ServletComponentScan
//mapper 接口类扫描包配置
@MapperScan(“com.zhiyi.shiro.mapper”)
大家可以参考我下面的配置类自己再用时可以直接 copy,稍作修改即可
package com.zhiyi.shiro.config;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
- 负责shiroBean的生命周期
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
/**
*这是个自定义的认证类,继承子AuthorizingRealm,负责用户的认证和权限处理
*/
@Bean
@DependsOn(“lifecycleBeanPostProcessor”)
public MyShiroRealm shiroRealm(){
MyShiroRealm realm = new MyShiroRealm();
//realm.setCredentialsMatcher(hashedCredentialsMatcher());
return realm;
}
/** 安全管理器
-
将realm加入securityManager
-
@return
*/
@Bean
public SecurityManager securityManager(){
//注意是DefaultWebSecurityManager!!!
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}
/** shiro filter 工厂类
-
1.定义ShiroFilterFactoryBean
-
2.设置SecurityManager
-
3.配置拦截器
-
4.返回定义ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
//1
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//2
//注册securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
logger.info(“注册安全管理器成功”);
//3
// 拦截器+配置登录和登录成功之后的url
//LinkHashMap是有序的,shiro会根据添加的顺序进行拦截
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//配置不会被拦截的连接 这里顺序判断
//anon,所有的url都可以匿名访问
//authc:所有url都必须认证通过才可以访问
//user,配置记住我或者认证通过才能访问
//logout,退出登录
//配置过滤器链,让静态资源可以自由随意访问
// filterChainDefinitionMap.put(“/JQuery/**”,“anon”);
// filterChainDefinitionMap.put(“/js/**”,“anon”);
// //配置退出过滤器
// filterChainDefinitionMap.put(“/example1”,“anon”);
// filterChainDefinitionMap.put(“/lxt”,“anon”);
// filterChainDefinitionMap.put(“/login”,“authc”);
// filterChainDefinitionMap.put(“/success”,“anon”);
// filterChainDefinitionMap.put(“/index”,“anon”);
// filterChainDefinitionMap.put(“/Register”,“anon”);
// filterChainDefinitionMap.put(“/logout”,“logout”);
// //过滤连接自定义,从上往下顺序执行,所以用LinkHashMap /**放在最下边
// filterChainDefinitionMap.put(“/**”,“authc”);
// //设置登录界面,如果不设置为寻找web根目录下的文件
shiroFilterFactoryBean.setLoginUrl(“/zhiyi”);
// //设置登录成功后要跳转的连接
// shiroFilterFactoryBean.setSuccessUrl(“/success”);
// //设置登录未成功,也可以说无权限界面
// shiroFilterFactoryBean.setUnauthorizedUrl(“/403”);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
logger.info(“shiro拦截工厂注入类成功”);
//4
//返回
return shiroFilterFactoryBean;
}
}
其中我注释掉了很多内容,但是需要什么服务自己开启即可
下面自己写一个 controller,service 测试一下,具体代码参考文章底部的 git 项目
Controller 层:
package com.zhiyi.shiro.controller;
import com.zhiyi.shiro.service.ShiroService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping(“shiro”)
public class ShiroController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
ShiroService shiroService;
@ResponseBody
@RequestMapping(“login”)
public Map<String,Object> login(@RequestParam(“userName”)String userName,@RequestParam(“passWord”)String passWord, HttpServletResponse response, HttpServletRequest request){
response.setHeader(“Access-Control-Allow-Origin”, request.getHeader(“Origin”));
response.setHeader(“Access-Control-Allow-Credentials”, “true”);// 允许服务器向浏览器跨域响应时更改浏览器(客户端)的cookie
Map<String,Object> map=new HashMap<String,Object>();
Subject subject=SecurityUtils.getSubject();//获取当前与系统交互的对象
return shiroService.confirmUserService(subject,userName,passWord,request);
}
}
Service 层:
package com.zhiyi.shiro.service;
import com.zhiyi.shiro.mapper.GetMapper;
import com.zhiyi.shiro.mapper.UpdateMapper;
import com.zhiyi.shiro.model.Shiro_User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
分享
1、算法大厂——字节跳动面试题
2、2000页互联网Java面试题大全
3、高阶必备,算法学习
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
家的负担。**[外链图片转存中…(img-V3avq1oD-1713465630257)]
[外链图片转存中…(img-54J1D5oR-1713465630258)]
[外链图片转存中…(img-duvEgmWL-1713465630258)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
分享
1、算法大厂——字节跳动面试题
[外链图片转存中…(img-VqifCLSp-1713465630258)]
2、2000页互联网Java面试题大全
[外链图片转存中…(img-vjiaPxqH-1713465630259)]
3、高阶必备,算法学习
[外链图片转存中…(img-3u3XwYks-1713465630259)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!