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
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.1.RELEASEversion>
<relativePath/>
parent>
<groupId>com.liuxigroupId>
<artifactId>spring-boot-shiroartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>spring-boot-shironame>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4jartifactId>
<version>1.3.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.1.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>3.7.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>4.3.12.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.8.7version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.2.2version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.2.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
添加依赖
yml配置:
server:
port: 8080
servlet: #启动jsp支持
init-parameters:
development: true
contextPath: /spssm
spring:
mvc:
view:
prefix: /WEB-INF/page/
suffix: .jsp
datasource:
url: jdbc:mysql://*:3306/*?useUnicode=true&characterEncoding=utf-8
username: root
password: *
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%n
log4j.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
*/
@Bean
public 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
*/
@Bean
public 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());
}
/**
* 切面拦截规则 参数会自动从容器中注入
*/
@Bean
public 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.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%n
log4j.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";
}
}
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2020/07/23
Time: 下午 1:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hellotitle>
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
*
FROM
permission
WHERE
id IN (
SELECT
rp.pid
FROM
USER u
LEFT JOIN user_role ur ON u.id = ur.uid
LEFT JOIN role_permission rp ON ur.rid = rp.rid
WHERE
u.id = 1
)
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 {
@Autowired
private UserMapper userMapper;
@Override
public int deleteByPrimaryKey(Integer id) throws Exception {
return userMapper.deleteByPrimaryKey(id);
}
@Override
public int insert(User record) throws Exception {
return userMapper.insert(record);
}
@Override
public int insertSelective(User record) throws Exception {
return userMapper.insertSelective(record);
}
@Override
public User selectByPrimaryKey(Integer id) throws Exception {
return userMapper.selectByPrimaryKey(id);
}
@Override
public int updateByPrimaryKeySelective(User record) throws Exception {
return userMapper.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(User record) throws Exception {
return userMapper.updateByPrimaryKey(record);
}
@Override
public 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 {
@Autowired
private PermissionMapper permissionMapper;
@Override
public int deleteByPrimaryKey(Integer id) throws Exception {
return permissionMapper.deleteByPrimaryKey(id);
}
@Override
public int insert(Permission record) throws Exception {
return permissionMapper.insert(record);
}
@Override
public int insertSelective(Permission record) throws Exception {
return permissionMapper.insertSelective(record);
}
@Override
public Permission selectByPrimaryKey(Integer id) throws Exception {
return permissionMapper.selectByPrimaryKey(id);
}
@Override
public int updateByPrimaryKeySelective(Permission record) throws Exception {
return permissionMapper.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(Permission record) throws Exception {
return permissionMapper.updateByPrimaryKey(record);
}
@Override
public 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
*
FROM
permission
WHERE
id IN (
SELECT
rp.pid
FROM
USER u
LEFT JOIN user_role ur ON u.id = ur.uid
LEFT JOIN role_permission rp ON ur.rid = rp.rid
WHERE
u.id = #{uid}
)
</select>
</mapper>
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 {
@Autowired
private UserService userService;
@Autowired
private PermissionService permissionService;
// 认证.登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
User user = null;
try {
UsernamePasswordToken utoken = (UsernamePasswordToken) token;// 获取用户输入的token
String username = utoken.getUsername();
user = userService.selectByName(username);
} catch (Exception e) {
e.printStackTrace();
}
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());// 放入shiro.调用CredentialsMatcher检验密码
}
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
User user = (User) principal.fromRealm(this.getClass().getName()).iterator().next();// 获取session中的用户
// 当前用户在系统上有什么权限,把拥有的权限设置到permissions
List<String> permissions = new ArrayList<>();
// 查询当前用户的拥有的所有的权限内容
List<Permission> list = null;
try {
list = permissionService.selectByUid(user.getId());
} catch (Exception e) {
e.printStackTrace();
}
for (Permission permission : list) {
// 不能存放空的权限到shiro
String url = permission.getUrl();
if (url != null && !"".equals(url)) {
permissions.add(url);
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);// 将权限放入shiro中.
return info;
}
}
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和登录成功的url
bean.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;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
@Qualifier("securityManager") SecurityManager manager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(manager);
return advisor;
}
}
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2020/07/23
Time: 下午 4:25
To 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: admin
Date: 2020/07/23
Time: 下午 1:01
To 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: admin
Date: 2020/07/23
Time: 下午 4:28
To 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>
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";
}
}