Idea Spring-boot整合shiro安全框架
shiro (java安全框架)
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
主要功能
三个核心组件:Subject, SecurityManager 和 Realms.
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
github:
https://github.com/1315998513/spring-boot-shiro
搭建spring-boot基础环境:
新建Spring-boot项目
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.liuxi</groupId><artifactId>spring-boot-shiro</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-boot-shiro</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><!--排除器--><exclusions><!--排除logging--><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!-- log4j. --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j</artifactId><version>1.3.8.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>3.7.5</version></dependency><!--引入web配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- servlet依赖. --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><!-- JSTL --><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId></dependency><!-- tomcat的支持. --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><!--<scope>provided</scope> --></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional><!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖myboot项目的项目如果想要使用devtools,需要重新引入 --></dependency><!-- spring aop支持 --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>4.3.12.RELEASE</version></dependency><!-- aspectj支持 注解的依赖 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version></dependency><!-- druid 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!-- shiro spring. --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.2.2</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.2.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
整合mybatis:
添加依赖
yml配置:
server:port: 8080servlet: #启动jsp支持init-parameters:development: truecontextPath: /spssm
spring:mvc:view:prefix: /WEB-INF/page/suffix: .jspdatasource:url: jdbc:mysql://*:3306/*?useUnicode=true&characterEncoding=utf-8username: rootpassword: *driver-class-name: com.mysql.jdbc.Driver
mybatis:mapperLocations: classpath:com/liuxi/mapper/xml/*.xml
整合德鲁伊连接池:
添加依赖
druid.properties:
log4j.rootLogger=info,A1,DRF
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5p [%F:%L] : %m%nlog4j.appender.DRF=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRF.Threshold=DEBUG
log4j.appender.DRF.DatePattern='.'yyyy-MM-dd
log4j.appender.DRF.File=logs/pms.log
log4j.appender.DRF.Append=true
log4j.appender.DRF.layout=org.apache.log4j.PatternLayout
log4j.appender.DRF.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}][%C{1}:%L] %m%n#log4j.logger.com.ibatis=DEBUG
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
#log4j.logger.java.sql.Connection=DEBUG
#log4j.logger.java.sql.Statement=DEBUG
#log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.com.liuxi.mapper=DEBUG
config下新建MybatisConfig:
package com.liuxi.config;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;import javax.sql.DataSource;
import java.sql.SQLException;/*** 数据库连接池配置** @author */
@Configuration
@PropertySource("classpath:druid.properties")
public class MybatisConfig {private Logger logger = LoggerFactory.getLogger(MybatisConfig.class);@Value("${spring.datasource.url}")private String dbUrl;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driverClassName;@Value("${spring.datasource.druid.initialSize}")private int initialSize;@Value("${spring.datasource.druid.minIdle}")private int minIdle;@Value("${spring.datasource.druid.maxActive}")private int maxActive;@Value("${spring.datasource.druid.maxWait}")private int maxWait;@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")private int timeBetweenEvictionRunsMillis;@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")private int minEvictableIdleTimeMillis;@Value("${spring.datasource.druid.validationQuery}")private String validationQuery;@Value("${spring.datasource.druid.testWhileIdle}")private boolean testWhileIdle;@Value("${spring.datasource.druid.testOnBorrow}")private boolean testOnBorrow;@Value("${spring.datasource.druid.testOnReturn}")private boolean testOnReturn;@Value("${spring.datasource.druid.filters}")private String filters;@Value("${spring.datasource.druid.logSlowSql}")private String logSlowSql;/*** 数据库连接池** @return*/@Bean("druidDataSource")public DataSource druidDataSource() {DruidDataSource datasource = new DruidDataSource();datasource.setUrl(dbUrl);datasource.setUsername(username);datasource.setPassword(password);datasource.setDriverClassName(driverClassName);datasource.setInitialSize(initialSize);datasource.setMinIdle(minIdle);datasource.setMaxActive(maxActive);datasource.setMaxWait(maxWait);datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);datasource.setValidationQuery(validationQuery);datasource.setTestWhileIdle(testWhileIdle);datasource.setTestOnBorrow(testOnBorrow);datasource.setTestOnReturn(testOnReturn);try {datasource.setFilters(filters);} catch (SQLException e) {logger.error("druid configuration initialization filter", e);}return datasource;}/*** 访问druid监控信息,查看sql语句执行情况 需要servlet支持** http://127.0.0.1:8080/spssm/druid/login.html** @return*/@Beanpublic ServletRegistrationBean druidServletRegistration() {ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");// 添加初始化参数:initParams// 白名单:registration.addInitParameter("allow", "127.0.0.1");// IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not// permitted to view this page.registration.addInitParameter("deny", "");// 登录查看信息的账号密码.registration.addInitParameter("loginUsername", "admin");registration.addInitParameter("loginPassword", "admin");// 是否能够重置数据.registration.addInitParameter("resetEnable", "false");return registration;}/*** 过滤druid** @return*/@Beanpublic FilterRegistrationBean druidStatFilter() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());// 添加过滤规则.filterRegistrationBean.addUrlPatterns("/*");// 添加不需要忽略的格式信息.filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");return filterRegistrationBean;}
}
整合事务:
添加依赖
在config新建:
package com.liuxi.config;import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;import java.util.Collections;
import java.util.HashMap;
import java.util.Map;/*** 事务拦截器*/
//@Configuration
public class TransactionAopConfig {/*** 事务拦截器*/@Bean("txInterceptor")TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) {return new TransactionInterceptor(tx, transactionAttributeSource());}/*** 切面拦截规则 参数会自动从容器中注入*/@Beanpublic AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) {AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();pointcutAdvisor.setAdvice(txInterceptor);pointcutAdvisor.setExpression("execution (* com.liuxi.service.*.*(..))");return pointcutAdvisor;}/*** 事务拦截类型*/@Bean("txSource")public TransactionAttributeSource transactionAttributeSource() {NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();/* 只读事务,不做更新操作 */RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();readOnlyTx.setReadOnly(true);readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);/* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务 */RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// requiredTx.setTimeout(5);Map<String, TransactionAttribute> txMap = new HashMap<>();txMap.put("insert*", requiredTx);txMap.put("update*", requiredTx);txMap.put("delete*", requiredTx);txMap.put("batch*", requiredTx);txMap.put("select*", readOnlyTx);source.setNameMap(txMap);return source;}}
整合log4j:
添加依赖
log4j.properties:
log4j.rootLogger=info,A1,DRF
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5p [%F:%L] : %m%nlog4j.appender.DRF=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRF.Threshold=DEBUG
log4j.appender.DRF.DatePattern='.'yyyy-MM-dd
log4j.appender.DRF.File=logs/pms.log
log4j.appender.DRF.Append=true
log4j.appender.DRF.layout=org.apache.log4j.PatternLayout
log4j.appender.DRF.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}][%C{1}:%L] %m%n#log4j.logger.com.ibatis=DEBUG
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
#log4j.logger.java.sql.Connection=DEBUG
#log4j.logger.java.sql.Statement=DEBUG
#log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.com.liuxi.mapper=DEBUG
测试运行
新建controller:
package com.liuxi.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class IndexController {@RequestMapping("index")public String index(){System.out.println(666);return "index";}
}
新建index.jsp:
index.jsp:
<%--Created by IntelliJ IDEA.User: adminDate: 2020/07/23Time: 下午 1:01To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>hello</title>
</head>
<body>
hello
</body>
</html>
访问:http://127.0.0.1:8080/spssm/index
数据库建表:
数据库有用户(user)、角色(role)、权限(permission)三个实体,除了实体表以外,为了实现表间用户与角色、角色与权限多对多的表间关系,所以产生了user_role、role_permission两张关系表。在下图中,使用红线将表的外键标记了出来,但为了方便并没有在表中创建外键,我们手动进行维护。
参考:
user:
role:
permission:
user_role:
role_permission:
编写sql语句:根据用户id查询出对应的权限:
SELECT DISTINCT*
FROMpermission
WHEREid IN (SELECTrp.pidFROMUSER uLEFT JOIN user_role ur ON u.id = ur.uidLEFT JOIN role_permission rp ON ur.rid = rp.ridWHEREu.id = 1)
结果:
生成实体类,mapper,mapperxml:
package com.liuxi.entity;public class User {private Integer id;private String username;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username == null ? null : username.trim();}public String getPassword() {return password;}public void setPassword(String password) {this.password = password == null ? null : password.trim();}
}
usermapper:
package com.liuxi.mapper;import com.liuxi.entity.User;public interface UserMapper {int deleteByPrimaryKey(Integer id);int insert(User record);int insertSelective(User record);User selectByPrimaryKey(Integer id);int updateByPrimaryKeySelective(User record);int updateByPrimaryKey(User record);User selectByName(String uname);
}
service:
package com.liuxi.service;import com.liuxi.entity.User;public interface UserService {int deleteByPrimaryKey(Integer id) throws Exception;int insert(User record) throws Exception;int insertSelective(User record) throws Exception;User selectByPrimaryKey(Integer id) throws Exception;int updateByPrimaryKeySelective(User record) throws Exception;int updateByPrimaryKey(User record) throws Exception;User selectByName(String uname) throws Exception;}
userserviceImpl:
package com.liuxi.impl;import com.liuxi.entity.User;
import com.liuxi.mapper.UserMapper;
import com.liuxi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic int deleteByPrimaryKey(Integer id) throws Exception {return userMapper.deleteByPrimaryKey(id);}@Overridepublic int insert(User record) throws Exception {return userMapper.insert(record);}@Overridepublic int insertSelective(User record) throws Exception {return userMapper.insertSelective(record);}@Overridepublic User selectByPrimaryKey(Integer id) throws Exception {return userMapper.selectByPrimaryKey(id);}@Overridepublic int updateByPrimaryKeySelective(User record) throws Exception {return userMapper.updateByPrimaryKeySelective(record);}@Overridepublic int updateByPrimaryKey(User record) throws Exception {return userMapper.updateByPrimaryKey(record);}@Overridepublic User selectByName(String uname) throws Exception {return userMapper.selectByName(uname);}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.liuxi.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.liuxi.entity.User"><id column="id" property="id" jdbcType="INTEGER"/><result column="username" property="username" jdbcType="VARCHAR"/><result column="password" property="password" jdbcType="VARCHAR"/></resultMap><select id="selectByName" resultType="com.liuxi.entity.User">select * from user where username=#{uname}</select>
</mapper>
psermission:
package com.liuxi.entity;public class Permission {private Integer id;private String name;private String url;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name == null ? null : name.trim();}public String getUrl() {return url;}public void setUrl(String url) {this.url = url == null ? null : url.trim();}
}
permissionMapper:
package com.liuxi.mapper;import com.liuxi.entity.Permission;import java.util.List;public interface PermissionMapper {int deleteByPrimaryKey(Integer id);int insert(Permission record);int insertSelective(Permission record);Permission selectByPrimaryKey(Integer id);int updateByPrimaryKeySelective(Permission record);int updateByPrimaryKey(Permission record);List<Permission> selectByUid(Integer uid);
}
service:
package com.liuxi.service;import com.liuxi.entity.User;public interface UserService {int deleteByPrimaryKey(Integer id) throws Exception;int insert(User record) throws Exception;int insertSelective(User record) throws Exception;User selectByPrimaryKey(Integer id) throws Exception;int updateByPrimaryKeySelective(User record) throws Exception;int updateByPrimaryKey(User record) throws Exception;User selectByName(String uname) throws Exception;}
impl:
package com.liuxi.impl;import com.liuxi.entity.Permission;
import com.liuxi.mapper.PermissionMapper;
import com.liuxi.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class PermissionServiceImpl implements PermissionService {@Autowiredprivate PermissionMapper permissionMapper;@Overridepublic int deleteByPrimaryKey(Integer id) throws Exception {return permissionMapper.deleteByPrimaryKey(id);}@Overridepublic int insert(Permission record) throws Exception {return permissionMapper.insert(record);}@Overridepublic int insertSelective(Permission record) throws Exception {return permissionMapper.insertSelective(record);}@Overridepublic Permission selectByPrimaryKey(Integer id) throws Exception {return permissionMapper.selectByPrimaryKey(id);}@Overridepublic int updateByPrimaryKeySelective(Permission record) throws Exception {return permissionMapper.updateByPrimaryKeySelective(record);}@Overridepublic int updateByPrimaryKey(Permission record) throws Exception {return permissionMapper.updateByPrimaryKey(record);}@Overridepublic List<Permission> selectByUid(Integer uid) throws Exception {return permissionMapper.selectByUid(uid);}
}
mapperXml:加入之前写好的SQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.liuxi.mapper.PermissionMapper"><resultMap id="BaseResultMap" type="com.liuxi.entity.Permission"><id column="id" property="id" jdbcType="INTEGER"/><result column="name" property="name" jdbcType="VARCHAR"/><result column="url" property="url" jdbcType="VARCHAR"/></resultMap><select id="selectByUid" resultType="com.liuxi.entity.Permission">SELECT DISTINCT*FROMpermissionWHEREid IN (SELECTrp.pidFROMUSER uLEFT JOIN user_role ur ON u.id = ur.uidLEFT JOIN role_permission rp ON ur.rid = rp.ridWHEREu.id = #{uid})</select></mapper>
Config添加登录授权类AuthRealm
package com.liuxi.config;import java.util.ArrayList;
import java.util.List;
import java.util.Set;import com.liuxi.entity.Permission;
import com.liuxi.entity.User;
import com.liuxi.service.PermissionService;
import com.liuxi.service.UserService;
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.authc.UsernamePasswordToken;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;@Component
public class AuthRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;@Autowiredprivate PermissionService permissionService;// 认证.登录@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {User user = null;try {UsernamePasswordToken utoken = (UsernamePasswordToken) token;// 获取用户输入的tokenString username = utoken.getUsername();user = userService.selectByName(username);} catch (Exception e) {e.printStackTrace();}return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());// 放入shiro.调用CredentialsMatcher检验密码}// 授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {User user = (User) principal.fromRealm(this.getClass().getName()).iterator().next();// 获取session中的用户// 当前用户在系统上有什么权限,把拥有的权限设置到permissionsList<String> permissions = new ArrayList<>();
// 查询当前用户的拥有的所有的权限内容List<Permission> list = null;try {list = permissionService.selectByUid(user.getId());} catch (Exception e) {e.printStackTrace();}for (Permission permission : list) {
// 不能存放空的权限到shiroString url = permission.getUrl();if (url != null && !"".equals(url)) {permissions.add(url);}}SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.addStringPermissions(permissions);// 将权限放入shiro中.return info;}}
添加上shiro的配置类
package com.liuxi.config;import java.util.LinkedHashMap;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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;/*** - shiro的配置类*/
@Configuration
public class ShiroConfiguration {//拦截的方法@Bean(name = "shiroFilter")public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();bean.setSecurityManager(manager);// 配置登录的url和登录成功的urlbean.setLoginUrl("/toLogin");// 去登录页面的地址bean.setUnauthorizedUrl("/noPer");bean.setSuccessUrl("/index");// 登录成功之后跳转的地址// 配置访问权限,需要使用LinkedHashMap,因为它必须保证有序LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// anon:所有url都都可以匿名访问// authc: 需要认证才能进行访问// user:配置记住我或认证通过可以访问// filterChainDefinitionMap.put("需要访问的url", "访问权限");filterChainDefinitionMap.put("/statics/*", "anon"); // 表示可以匿名访问filterChainDefinitionMap.put("/toLogin", "anon");filterChainDefinitionMap.put("/login", "anon");filterChainDefinitionMap.put("/**", "authc");// 表示需要认证才可以访问bean.setFilterChainDefinitionMap(filterChainDefinitionMap);return bean;}// 配置核心安全事务管理器@Bean(name = "securityManager")public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {System.err.println("--------------shiro已经加载----------------");DefaultWebSecurityManager manager = new DefaultWebSecurityManager();manager.setRealm(authRealm);return manager;}@Beanpublic LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}@Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();creator.setProxyTargetClass(true);return creator;}@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(manager);return advisor;}
}
添加页面:
login:
<%--Created by IntelliJ IDEA.User: adminDate: 2020/07/23Time: 下午 4:25To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><form action="${pageContext.request.contextPath}/login">账户:<input type="text" name="user"><br>密码:<input type="password" name="pwd"><br><input type="submit" value="登陆"></form>
</body>
</html>
index功能页面添加上
导入shiro标签库<%@ taglib uri=“http://shiro.apache.org/tags” prefix=“shiro”%>
在按钮上添加,如果有权限就会显示标签内容,没有则不显示
<shiro:hasPermission name="/xxx"></shiro:hasPermission>
<%--Created by IntelliJ IDEA.User: adminDate: 2020/07/23Time: 下午 1:01To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<html>
<head><title>hello</title>
</head>
<body>
欢迎您登陆,${user.username}<shiro:hasPermission name="/insert"><a href="${pageContext.request.contextPath}/insert">新增</a>
</shiro:hasPermission><shiro:hasPermission name="/update"><a href="${pageContext.request.contextPath}/update">修改</a>
</shiro:hasPermission><shiro:hasPermission name="/delete"><a href="${pageContext.request.contextPath}/delete">删除</a>
</shiro:hasPermission><shiro:hasPermission name="/select"><a href="${pageContext.request.contextPath}/select">查询</a>
</shiro:hasPermission><a href="${pageContext.request.contextPath}/logout">登出</a>
</body>
</html>
<%--Created by IntelliJ IDEA.User: adminDate: 2020/07/23Time: 下午 4:28To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
删除
</body>
</html>
IndexController编写登陆登出等等逻辑和权限控制
package com.liuxi.controller;import com.liuxi.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpSession;@Controller
public class IndexController {@RequestMapping("index")public String index(){System.out.println(666);return "index";}@RequestMapping("login")public String login(String user, String pwd, ModelMap map, HttpSession session) throws Exception {UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user, pwd);Subject subject = SecurityUtils.getSubject();try {subject.login(usernamePasswordToken); // 完成登录User user2 = (User) subject.getPrincipal();session.setAttribute("user", user2);return "redirect:/";} catch (Exception e) {return "login";// 返回登录页面}}@RequestMapping("/logout")public String logout(HttpSession session) {//先remove session作用域的用户信息session.removeAttribute("user");//再shiro框架做logout操作Subject subject = SecurityUtils.getSubject();subject.logout();return "redirect:/toLogin";}@RequestMapping("toLogin")public String toLogin(){System.out.println(666);return "login";}@RequiresPermissions("/insert") // @RequiresPermissions("添加权限的url")使用来添加权限的@RequestMapping("insert")public String insert(){return "/user/insert";}@RequiresPermissions("/update")@RequestMapping("update")public String update(){return "/user/update";}@RequiresPermissions("/select")@RequestMapping("select")public String select(){return "/user/select";}@RequiresPermissions("/delete")@RequestMapping("delete")public String delete(){return "/user/delete";}
}
效果:
Idea Spring-boot整合shiro安全框架相关推荐
- Spring Boot整合Shiro + Springboot +vue
目录 02 Spring Boot整合Shiro p1.shiro概述 1 什么是Shiro 2 Shiro核心组件 p2.Shiro实现登录认证 AccountRealm.java QueryWra ...
- Spring Boot 整合 shiro 之盐值加密认证详解(六)
Spring Boot 整合 shiro 之盐值加密认证详解 概述 不加盐认证 加入密码认证核心代码 修改 CustomRealm 新增获取密文的方法 修改 doGetAuthenticationIn ...
- Spring Boot 整合 Shiro(三)Kaptcha验证码 附源码
前言 本文是根据上篇<Spring Boot 整合Shiro(二)加密登录与密码加盐处理>进行修改,如有不明白的转上篇文章了解. 1.导入依赖 <!-- https://mvnrep ...
- 六、Spring Boot整合Shiro
六.Spring Boot整合Shiro 6.1.整合思路 6.2.创建spring boot项目 6.3.引入shiro依赖 6.4.配置shiro环境 创建配置类ShiroConfig 1.配置: ...
- Spring Boot整合Shiro + JSP教程(用户认证,权限管理,图片验证码)
在此首先感谢**编程不良人**up主提供的视频教程 代码都是跟着up的视频敲的,遇到的一些问题也是通过CSDN博主提供的教程解决的,在此也感谢那些提供bug解决方案的前辈们~ 项目完整代码已经发布到g ...
- spring boot整合shiro继承redis_Springboot+Shiro+redis整合
1.Shiro是Apache下的一个开源项目,我们称之为Apache Shiro.它是一个很易用与Java项目的的安全框架,提供了认证.授权.加密.会话管理,与spring Security 一样都是 ...
- spring boot整合shiro+jjwt
前言 本篇文章将教大家在 shiro + springBoot 的基础上整合 JJWT (JSON Web Token) JWT JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允 ...
- spring boot整合Shiro实现单点登录
默认情况下,Shiro已经为我们实现了和Cas的集成,我们加入集成的一些配置就ok了 1.加入shiro-cas包 <!-- shiro整合cas单点 --><dependency& ...
- Spring Boot 整合 Shiro
虽然,直接用Spring Security和SpringBoot 进行"全家桶式"的合作是最好不过的,但现实总是欺负我们这些没办法决定架构类型的娃子. Apache Shiro 也 ...
- spring boot整合shiro继承redis_spring-boot-plus集成Shiro+JWT权限管理
SpringBoot+Shiro+JWT权限管理 Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 使用Shiro的易于理解的API,您可以 ...
最新文章
- 算法--------删除重复元素,但保留两个
- c++ cuda拷贝内存
- 用access做考场桌贴_利用Word、Excel、Access进行考务安排及学生成绩分析的有效途径-教育文档...
- Delphi中的容器类
- 文件得编码和文件名的编码是不一样的
- WSL1 升级为 WSL2
- [转载]Validation of viewstate MAC failed异常的原因及解决方法
- 创业者没有周末,但有周期
- MySQL数据库学习2 - 数据库的操作
- matlab符号函数与对其的常用操作
- window10刷新卡顿
- Linux基础命令的那些事儿(1)
- C个java都是多线程语言对吗_Java里的多线程
- Android 9 Pie
- Microsoft Visual Studio 2019 美化之——透明化窗口 Microsoft Visual Studio 2019 C/C++ Windows 下重量级编辑器 Editor
- NOI2010~NOI2018选做
- PYQT5 打包后无法显示jpg图片问题
- 酒吧类型与其娱乐项目设置
- C 语言 结构体_finddata_t _findfirst, _findnext, _findclose 函数讲解
- Redis(上)基础及8种数据类型