2を統合するための最も簡単な整頓最近の研究springbootと史郎、。
1、瓶包:
ここでは、親とのjarパッケージのバージョンを統一。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jasper是tomcat中使用的JSP引擎 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!-- shiro相关包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
2、設定ファイルには、リソースのapplication.propertiesと史郎キャッシュファイルehcache.xmlをspringboot必要があります。
まず:コメントして設定をapplication.properties、あまりの話ではありません。
#修改服务器端口号和项目根路径
server.port=8080
server.servlet.context-path=/shiro
# 设置包的日志级别为debug(这里demo是我的总包,你可以写任意一个包)
logging.level.demo=debug
#jdbc属性
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hibernate?useSSL=false&serverTimezone=Hongkong&characterEncoding=utf-8&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=1234
# mybatis 别名扫描
mybatis.type-aliases-package=demo.pojo
# mapper.xml文件位置,如果没有映射文件,请注释掉
mybatis.mapper-locations=classpath:mappers/*.xml
# jsp配置(如果用官方推荐的thymeleaf,就不用写了,有默认值)
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
# springboot 提供多环境配置的机制
spring.profiles.active=dev
そして、ehcache.xmlファイル:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="D:/tmpdir"/>
<!--
缓存配置:
maxElementsInMemory:内存中最大存放的元素的个数
eternal:缓存的数据是否永生
timeToIdleSeconds:闲置多久清除,单位秒
timeToLiveSeconds:存活多久清除,单位秒
overflowToDisk: 缓存存储的数据达到maxElementsInMemory限制时是否overflow到磁盘
maxElementsOnDisk:缓存到硬盘上最大的元素个数
diskExpiryThreadIntervalSeconds:过期轮询时间,单位秒
memoryStoreEvictionPolicy:内存存储和清除策略,
默认三个策略,分别为LRU(最近最少使用)、LFU(最常用的)、FIFO(先进先出)。
-->
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
3、注釈のJavaとspring.xmlシロ-Bean構成の構成において:
これは、2つのノートを使用しています。
- @Configuration`:声明一个类作为配置类,代替xml文件
- @Bean:声明在方法上,将方法的返回值加入Bean容器,代替`<bean>`标签
@Configuration
public class ShiroConfig {
/*开启shiro缓存*/
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
return ehCacheManager;
}
/*凭证匹配器:身份认证*/
@Bean
public HashedCredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
/*自定义realm*/
@Bean
public UserRealm userRealm(UserService userService) {
UserRealm userRealm = new UserRealm();
userRealm.setUserService(userService);
userRealm.setCredentialsMatcher(credentialsMatcher());
//userRealm开启缓存
userRealm.setCachingEnabled(true);
//开启权限缓存
userRealm.setAuthorizationCacheName("authorizationCache");
userRealm.setAuthorizationCachingEnabled(true);
return userRealm;
}
//安全管理器
//所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;
//可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互
//可以把它看成 DispatcherServlet 前端控制器;
//SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法
@Bean
public DefaultWebSecurityManager securityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置自定义Realm.也可以传realm集合。securityManager.setRealms(list)
securityManager.setRealm(userRealm);
securityManager.setCacheManager(ehCacheManager());
return securityManager;
}
/*shiro拦截器做配置*/
@Bean
public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/tologin");
shiroFilterFactoryBean.setSuccessUrl("/index");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/tologin", "anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/index", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/admin/**", "authc");
filterChainDefinitionMap.put("/user/add", "authc");
filterChainDefinitionMap.put("/user/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/*生命周期前置处理器bean*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/*shiro AOP*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor a = new AuthorizationAttributeSourceAdvisor();
a.setSecurityManager(securityManager);
return a;
}
/* - Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run:*/
/*开启shiro注释,并且需要lifecycleBeanProcessor存在*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator d = new DefaultAdvisorAutoProxyCreator();
d.setProxyTargetClass(true);
return d;
}
}
図4に示すように、構成された、シロ認証プロセスに従ってコードと相まって。
トークンに詰めユーザーによってアップロードされた収集身元情報、コールsubject.login()
@RequestMapping("login")
public String login(HttpServletRequest request) {
//用户上传的身份信息
String username = request.getParameter("username");
String password = request.getParameter("password");
String msg = null;
//包装成token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//调用subject.login()
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch (UnknownAccountException e) {
e.printStackTrace();
msg = "账号错误";
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
msg = "密码错误";
} catch (Exception e) {
e.printStackTrace();
msg = "其他错误";
}
if (null != msg) {
request.setAttribute("msg", msg);
return "login";
}
//下面的代码可以替换成用户身份下的某个角色
Session session = subject.getSession();
System.out.println("session = " + session.getClass());
System.out.println("session = " + session.getId());
session.setAttribute("roleId", 1);
return "index";
}
ユーザ認証が正しい場合、それはメインページに移動しますindex.htmlを
:doGetAuthenticationInfo認証方法の下に取り付けられた
四つのパラメータAuthenticationInfoこのメソッドによって返されるオブジェクトである:
プリンシパル:識別、被験者のすなわち識別属性は。データベースからの一般的。
資格証明書:証明書/バウチャー。ユーザ入力。
credentialsSalt:暗号化されたソルト値
realmNameに:realmNameに
UserRealm.class:
public class UserRealm extends AuthorizingRealm {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
System.out.println("roleId=" + session.getAttribute("roleId"));
System.out.println("session = " + session.getId());
//通过查库得到角色与权限数据 userService.getPermsByRoleId(roleId)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(userService.getRoles());
info.addStringPermissions(userService.getPerms());
System.out.println("==========授权==========");
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = token.getPrincipal().toString();
// User user = userService.findByUsername(username);
// 数据库中查询出的加密过的密码 原值=admin
String password = "d0fbeefddc1cb9b0f9b4bcdd5b50b8cc";
// 可以从数据库中查询
String salt = "skeye";
//
User user = new User();
user.setUsername(username);
System.out.println("==========认证");
// 参数依次:principal,hashedCredentials,credentialsSalt,realmName
return new SimpleAuthenticationInfo
(user, password, ByteSource.Util.bytes(salt), getName());
}
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
}
5、権限認証プロセス:
同行コード:
対応するコントローラメソッドの機能を同行するために必要な権限
@Controller
@RequestMapping()
public class AuthController {
@RequestMapping("/admin/add")
@RequiresPermissions("/admin/add")
public String addAdmin() {
return "adminAdd";
}
@RequestMapping("/user/add")
@RequiresPermissions("/user/add")
public String addUser() {
return "userAdd";
}
}
コードを検証するdoGetAuthenticationInfo方法は、上記userRealm.classで結合されています。
6、スイッチの役割
(史郎キャッシュメカニズムを使用すると、アクセス許可のキャッシュを持っている場合、それはライブラリのアップデートキャッシュをチェックして行くことはありませんですので、クリーンアップキャッシュ権情報)最後に、ログイン状態の下で機能スイッチの役割を実現付けます。
まずloginAgain方法を添付:このメソッドは、毎回のスイッチングを実行します。
ここでは明確なキャッシュ方式であるUserRealmです。
@RequestMapping("loginAgain")
public String login2(HttpServletRequest request) {
PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
UserRealm userRealm = MyApplicationContextUtils.getBean(UserRealm.class);
// 清除授权缓存
userRealm.clearCachedAuthorizationInfo(principals);
System.out.println(" ==========清理授权缓存==========");
return "index";
}
AuthorizingRealm.classで史郎明確なキャッシュ機能、実際に達成されて、私たちはそれを呼び出す:
史郎出典:
protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
if (principals != null) {
Cache<Object, AuthorizationInfo> cache = this.getAvailableAuthorizationCache();
if (cache != null) {
Object key = this.getAuthorizationCacheKey(principals);
cache.remove(key);
}
}
}
これは、保護された方法です。パッケージのFeizi異なる種類のは、私たちがこのメソッドをオーバーライドする必要があり、呼び出すことはできません。私達はちょうどUseRealm方法はAuthorizingRealm、親クラスのメソッドへの直接参照を継承しています。
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
最後に、問題がある豆工場豆に登録したクラスあるUserRealmを取得する方法である:
内部クラスを開始するメソッドの戻り値は、私たちがBeanクラスを介してそれを得ることができ、実際にたBeanFactory実装クラスのサブクラスです:
springboot下回りますユーティリティクラスによって保存された内部クラスConfigurableApplicationContextの戻り値の起動方法。
@SpringBootApplication
public class ShiroApp {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ShiroApp.class);
MyApplicationContextUtils.setApplicationContext(applicationContext);
}
}
ツールコード:ランダムのような
public class MyApplicationContextUtils {
private static ApplicationContext applicationContext;
public static void setApplicationContext(ApplicationContext applicationContext) {
MyApplicationContextUtils.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
[OK]を、簡単なここでの設定、および更新後にプロジェクトを完了します。
詳細はお問い合わせくださいます。https://www.w3cschool.cn/shiro/