springboot整合shiro安全框架
1.创建springboot工程
2.引入依赖
<dependencies>
<!-- my的依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!-- thymeleaf依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--数据路连接-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--shiro和springboot整合的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3.application配置文件
#连接数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///shiro?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
#thymeleaf的视图解析器
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
#shiro配置文件需要的值|密码加密器
shiro.hashAlgorithmName=MD5
shiro.hashIterations=1024
4.编写实体类和dao类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission {
@TableId(type = IdType.AUTO) //注解列名如果不是id ,则需要使用TableId注解
private Integer perid;
private String pername;
private String percode;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
//自动递增
@TableId(type = IdType.AUTO) //注解列名如果不是id ,则需要使用TableId注解
Integer userid;
String username;
String userpwd;
String sex;
String address;
String salt;
}
(5)编写UserService
@Override
public User findUserByUsername(String username) {
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("username",username);
User user = userDao.selectOne(userQueryWrapper);
return user;
}
(6)编写realm
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取登录账号
final String username = authenticationToken.getPrincipal().toString();
//根据账号获取用户信息
User user = userService.findUserByUsername(username);
if(user!=null){
final ByteSource salt = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info= new SimpleAuthenticationInfo(user,user.getUserpwd(),salt,this.getName());
return info;
}
return null;
}
}
(7)编写LoginController
@Controller
//将后端返回的数据转为json格式
//esponseBody
public class LoginController {
@PostMapping("/login")
public Stringn(LoginVo loginVo){
final Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUsername(),loginVo.getPassword());
try{
subject.login(token);
//登录成功返回200
return "success;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
//未登陆时跳转的路径
@GetMapping("/unlogin")
@ResponseBody
public Result unlogin(){
return new Result(401,"未登录",null);
}
}
(8)编写shiro配置类
@Configuration//配置类
public class ShiroConfig {
//获得配置文件中的值
@Value("${shiro.hashIterations}")
private int hashIterations;
@Value("${shiro.hashAlgorithmName}")
private String hashAlgorithmName;
@Bean
public DefaultWebSecurityManager securityManager(){
final DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(myRealm());
return manager;
}
@Bean
public MyRealm myRealm(){
final MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher());
return myRealm;
}
@Bean
public HashedCredentialsMatcher credentialsMatcher(){
final HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//加密使用加密器
matcher.setHashAlgorithmName(hashAlgorithmName);
//密码加密次数
matcher.setHashIterations(hashIterations);
return matcher;
}
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean factoryBean(){
final ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
shiroFilterFactoryBean.setLoginUrl("/login.html");
//设置过滤规则
final HashMap<String, String> map = new HashMap<>();
map.put("/login","anon");
map.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//注册过滤器
@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean(){
final FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new DelegatingFilterProxy());
filterFilterRegistrationBean.setName("shiroFilter");
filterFilterRegistrationBean.addUrlPatterns("/*");
return filterFilterRegistrationBean;
}
}
(9)编写登录界面
(10)编写登录成功界面
springboot整合shiro--授权【权限】
(1)修改Myrealm
@Autowired
private PermissionService permissionService;
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取当前登录者的账号|对象
User user = (User) principalCollection.getPrimaryPrincipal();
//调用userSerice中的方法--根据id
List<String> permission = permissionService.findPermissionByUserId(user.getUserid());
if(permission.size()!=0){
SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
System.out.println("--------------");
info.addStringPermissions(permission);
return info;
}
return null;
}
(2)编写PermissionService
@Service
public class PermissionServiceImpl implements PermissionService {
@Autowired
private PermissionDao permissionDao;
@Override
public List<String> findPermissionByUserId(Integer userid) {
final List<Permission> permission = permissionDao.findPermissionByUserId(userid);
final List<String> collect = permission.stream().map(Permission::getPercode).collect(Collectors.toList());
return collect;
}
}
(3Permissiondao和映射文件
(4)浏览器观察
发现所有的权限都显示,我们的前端页面shiro标签并没有生效
(5)shrio和thymeleaf集成的扩展依赖
<!--shrio和thymeleaf集成的扩展依赖,为了能在页面上使用xsln:shrio的标签 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
(6)修改shiro配置类
/**
* 这里是为了能在html页面引用shiro标签,
*/
@Bean(name = "shiroDialect")
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
后面就是将前后端不分离改为前后端分离,还整合了redis,避免多次权限查询:仓库地址:gitee.com/junjie-chen…