Shiro大概原理和快速开始
生活随笔
收集整理的這篇文章主要介紹了
Shiro大概原理和快速开始
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Shiro大概原理和快速開始
shiro快速開始-helloshiro(官網(wǎng)教程:http://shiro.apache.org/10-minute-tutorial.html)
1.下載 shiro -master.zip
2.添加依賴
<dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency> </dependencies>2.添加log4j.properties
log4j.rootLogger=INFO, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n# General Apache libraries log4j.logger.org.apache=WARN# Spring log4j.logger.org.springframework=WARN# Default Shiro logging log4j.logger.org.apache.shiro=INFO# Disable verbose logging log4j.logger.org.apache.shiro.util.ThreadContext=WARN log4j.logger.org.apache.3.添加shiro.ini文件
# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # ============================================================================= # Quickstart INI Realm configuration # # For those that might not understand the references in this file, the # definitions are all based on the classic Mel Brooks' film "Spaceballs". ;) # =============================================================================# ----------------------------------------------------------------------------- # Users and their assigned roles # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc # ----------------------------------------------------------------------------- [users] # user 'root' with password 'secret' and the 'admin' role root = secret, admin # user 'guest' with the password 'guest' and the 'guest' role guest = guest, guest # user 'presidentskroob' with password '12345' ("That's the same combination on # my luggage!!!" ;)), and role 'president' presidentskroob = 12345, president # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz' darkhelmet = ludicrousspeed, darklord, schwartz # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz' lonestarr = vespa, goodguy, schwartz# ----------------------------------------------------------------------------- # Roles with assigned permissions # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc # ----------------------------------------------------------------------------- [roles] # 'admin' role has all permissions, indicated by the wildcard '*' admin = * # The 'schwartz' role can do anything (*) with any lightsaber: schwartz = lightsaber:* # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with # license plate 'eagle5' (instance specific id) goodguy = winnebago:drive:eagle54.添加quickstart.java
/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied. See the License for the* specific language governing permissions and limitations* under the License.*/import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*;import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory;/*** Simple Quickstart application showing how to use Shiro's API.** @since 0.9 RC2*/ public class Quickstart {private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);public static void main(String[] args) {// The easiest way to create a Shiro SecurityManager with configured// realms, users, roles and permissions is to use the simple INI config.// We'll do that by using a factory that can ingest a .ini file and// return a SecurityManager instance:// Use the shiro.ini file at the root of the classpath// (file: and url: prefixes load from files and urls respectively):Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();// for this simple example quickstart, make the SecurityManager// accessible as a JVM singleton. Most applications wouldn't do this// and instead rely on their container configuration or web.xml for// webapps. That is outside the scope of this simple quickstart, so// we'll just do the bare minimum so you can continue to get a feel// for things.SecurityUtils.setSecurityManager(securityManager);// Now that a simple Shiro environment is set up, let's see what you can do:// get the currently executing user://獲取當前的用戶對象subjectSubject currentUser = SecurityUtils.getSubject();//通過當前用戶獲取Session// Do some stuff with a Session (no need for a web or EJB container!!!)Session session = currentUser.getSession();session.setAttribute("someKey", "aValue");String value = (String) session.getAttribute("someKey");if (value.equals("aValue")) {log.info("Retrieved the correct value! [" + value + "]");}//判斷當前用戶數(shù)是否被認證// let's login the current user so we can check against roles and permissions:if (!currentUser.isAuthenticated()) {//Token :令牌 ,沒有獲取,隨機UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");token.setRememberMe(true); //設置記住我try {currentUser.login(token); //執(zhí)行登錄操作} catch (UnknownAccountException uae) {log.info("There is no user with username of " + token.getPrincipal());} catch (IncorrectCredentialsException ice) {log.info("Password for account " + token.getPrincipal() + " was incorrect!");} catch (LockedAccountException lae) {log.info("The account for username " + token.getPrincipal() + " is locked. " +"Please contact your administrator to unlock it.");}// ... catch more exceptions here (maybe custom ones specific to your application?catch (AuthenticationException ae) {//unexpected condition? error?}}//say who they are://print their identifying principal (in this case, a username):log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");//test a role:if (currentUser.hasRole("schwartz")) {log.info("May the Schwartz be with you!");} else {log.info("Hello, mere mortal.");}//粗粒度//test a typed permission (not instance-level)if (currentUser.isPermitted("lightsaber:wield")) {log.info("You may use a lightsaber ring. Use it wisely.");} else {log.info("Sorry, lightsaber rings are for schwartz masters only.");}//細粒度5//a (very powerful) Instance Level permission:if (currentUser.isPermitted("winnebago:drive:eagle5")) {log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +"Here are the keys - have fun!");} else {log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");}//all done - log out!currentUser.logout();System.exit(0);} }shiro整合springboot環(huán)境(實現(xiàn)一個簡單的登錄頁面)
1.添加項目依賴
<!-- thymeleaf--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-java8time</artifactId></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.3.2</version></dependency><!--shiro-thymeleaf整合 --><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency><!--連接數(shù)據(jù)庫所需要的依賴 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version></dependency><!--web所需要的依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><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><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.1</version><scope>compile</scope></dependency>2.引入thymeleaf的命名空間
xmlns:th="http://thymeleaf.org"3.項目結構圖:
Shiro實現(xiàn)登錄攔截(shiro.config)
1.ShiroConfig.java
package com.seer.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap; import java.util.Map;@Configuration public class ShiroConfig {//ShiroFilterFactoryBean 3@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("security") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//設置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的內(nèi)置過濾器/** anno:無需認證就可以訪問* authc:必須認證才可以訪問* user:必須擁有記住我功能才能訪問* perms;擁有某個資源的權限才能訪問* role:擁有某個角色權限才能訪問* */Map<String, String> filterMap=new LinkedHashMap<>();//攔截//授權,正常的情況下,沒有授權會跳轉到?jīng)]授權頁面filterMap.put("/user/add","perms[user:add]");filterMap.put("/user/update","perms[user:update]");filterMap.put("/user/*","authc");bean.setFilterChainDefinitionMap(filterMap);//設置登錄的請求bean.setLoginUrl("/toLogin");//設置沒授權的跳轉bean.setUnauthorizedUrl("/noauth");return bean; }//DefaultWebSecurityManager 2@Bean(name = "security") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm ){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯(lián)UserRealmsecurityManager.setRealm(userRealm);return securityManager; }//創(chuàng)建realm對象,需要自定義類 1@Bean public UserRealm userRealm(){return new UserRealm(); }//整合shiroDialect:用來整合shiro和thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();} }Shiro實現(xiàn)用戶認證和授權
1.UserRealm.java
package com.seer.config;import com.seer.pojo.User; import com.seer.service.UserService; import org.apache.shiro.SecurityUtils; 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.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;public class UserRealm extends AuthorizingRealm {//引入業(yè)務層@AutowiredUserService userService;//授權@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("執(zhí)行了=》授權");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//拿到當前登錄的這個對象Subject subject = SecurityUtils.getSubject();User currentUser = (User) subject.getPrincipal(); //拿到User對象//設置當前用戶的權限info.addStringPermission(currentUser.getPerm());return info;}//認證@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("執(zhí)行了=》認證");//用戶名,密碼,數(shù)據(jù)中取UsernamePasswordToken userToken= (UsernamePasswordToken)token;//數(shù)據(jù)庫查詢得到的用戶User user = userService.getUserByusername(userToken.getUsername());if (user==null){ //沒有這個人就會報UnknownAccountException異常return null;}//密碼認證,shiro做return new SimpleAuthenticationInfo(user,user.getPwd(),"");} }Shiro整合mybatis
1.Mycontroller.java
package com.seer.controller;import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;@Controller public class MyController {//首頁@RequestMapping({"/","/index"})public String toindex(Model model){model.addAttribute("msg","helloshiro!");return "index";}//添加@RequestMapping("/user/add")public String add(){return "user/add";}//修改@RequestMapping("/user/update")public String update(){return "user/update";}//首頁@RequestMapping("/toLogin")public String tologin(){return "login";}//執(zhí)行登錄@RequestMapping("/login")public String login(String username, String password,Model model){//獲取當前用戶Subject subject = SecurityUtils.getSubject();//封裝用戶的登錄數(shù)據(jù)UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {subject.login(token);return "index"; //登陸成功返回首頁} catch (UnknownAccountException e) { //用戶名錯誤model.addAttribute("msg","用戶名錯誤");return "login";} catch (IncorrectCredentialsException e) { //密碼錯誤model.addAttribute("msg","密碼錯誤");return "login";}}//無授權跳轉頁面@RequestMapping("/noauth")@ResponseBodypublic String unauthorized(){return "沒授權無法訪問此頁面";} }2.編寫實體類–User.java
package com.seer.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class User {private int id;private String username;private String pwd;private String perm; }3.application.yml
#DataSource Config spring:datasource:username: rootpassword: 12345driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testjdbc?useUnicode=true&useSSL=false&characterEncoding=utf-8&serverTimezone=UTCtype: com.alibaba.druid.pool.DruidDataSource #自定義的druid數(shù)據(jù)源#Spring Boot 默認是不注入這些屬性值的,需要自己綁定#druid 數(shù)據(jù)源專有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置監(jiān)控統(tǒng)計攔截的filters,stat:監(jiān)控統(tǒng)計、log4j:日志記錄、wall:防御sql注入#如果允許時報錯 java.lang.ClassNotFoundException: org.apache.log4j.Priority#則導入 log4j 依賴即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 mybatis:type-aliases-package: com.seer.pojomapper-locations: classpath:mybatis/mapper/*.xml4.編寫mapper和mapper.xml
UserMapper.java
package com.seer.mapper;import com.seer.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; //@Mapper : 表示本類是一個 MyBatis 的 Mapper @Mapper @Repository public interface UserMapper {//通過用戶名查找用戶public User getUserByusername(String username); }UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.seer.mapper.UserMapper"><select id="getUserByusername" resultType="User" parameterType="String">select * from user where username= #{username} ;</select></mapper>5.編寫業(yè)務層
UserService.java
package com.seer.service;import com.seer.pojo.User;public interface UserService {public User getUserByusername (String username);}UserServiceImpl.java
package com.seer.service;import com.seer.mapper.UserMapper; import com.seer.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepublic User getUserByusername(String username) {return userMapper.getUserByusername(username);} }Shiro整合Thymeleaf
1.導入命名空間
xmlns:th="www.thymeleaf.org/thymeleaf-extras-shiro"Shiro-登錄大致的實現(xiàn)流程
1.第一步:在Controller中獲取當前用戶subject,封裝當前用戶的登錄數(shù)據(jù)成Token,執(zhí)行subject的login()方法。
//執(zhí)行登錄 @RequestMapping("/login") public String login(String username, String password,Model model){//獲取當前用戶Subject subject = SecurityUtils.getSubject();//封裝用戶的登錄數(shù)據(jù)UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {subject.login(token);return "index"; //登陸成功返回首頁} catch (UnknownAccountException e) { //用戶名錯誤model.addAttribute("msg","用戶名錯誤");return "login";} catch (IncorrectCredentialsException e) { //密碼錯誤model.addAttribute("msg","密碼錯誤");return "login";}}其中SecurityUtils.getSubject()是怎么獲取到當前用戶信息的?:根據(jù)前臺傳回的cookie,通過shrio的 SessionManager 去獲取到對應的seesionid,然后再綁定到線程上,通過線程獲取subject。
2.第二步:執(zhí)行認證
//認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("執(zhí)行了=》認證");//用戶名,密碼,數(shù)據(jù)中取UsernamePasswordToken userToken= (UsernamePasswordToken)token;//數(shù)據(jù)庫查詢得到的用戶User user = userService.getUserByusername(userToken.getUsername());if (user==null){ //沒有這個人就會報UnknownAccountException異常return null;}//密碼認證,shiro做return new SimpleAuthenticationInfo(user,user.getPwd(),"");}3.第三步執(zhí)行授權
//授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("執(zhí)行了=》授權");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//拿到當前登錄的這個對象Subject subject = SecurityUtils.getSubject();User currentUser = (User) subject.getPrincipal(); //拿到User對象//設置當前用戶的權限info.addStringPermission(currentUser.getPerm());return info; }4.第四步:ShiroFilterFactoryBean 過濾器攔截
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("security") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//設置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的內(nèi)置過濾器/** anno:無需認證就可以訪問* authc:必須認證才可以訪問* user:必須擁有記住我功能才能訪問* perms;擁有某個資源的權限才能訪問* role:擁有某個角色權限才能訪問* */Map<String, String> filterMap=new LinkedHashMap<>();//攔截//授權,正常的情況下,沒有授權會跳轉到?jīng)]授權頁面filterMap.put("/user/add","perms[user:add]");filterMap.put("/user/update","perms[user:update]");filterMap.put("/user/*","authc");bean.setFilterChainDefinitionMap(filterMap);//設置登錄的請求bean.setLoginUrl("/toLogin");//設置沒授權的跳轉bean.setUnauthorizedUrl("/noauth");return bean; }這一步中有三個重要的方法
//創(chuàng)建realm對象,需要自定義類 1@Bean public UserRealm userRealm(){return new UserRealm(); }//DefaultWebSecurityManager 2@Bean(name = "security") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm ){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯(lián)UserRealmsecurityManager.setRealm(userRealm);return securityManager; }@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("security") DefaultWebSecurityManager defaultWebSecurityManager){、、、return bean; }由此看出:執(zhí)行的順序為: MyReaml–>SecurityManager–>ShiroFilterFactoryBean
總結
以上是生活随笔為你收集整理的Shiro大概原理和快速开始的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RGB相机、深度相机以及LiDAR成像原
- 下一篇: 远程桌面卡顿