Apache Shiro ialah rangka kerja (kebenaran) keselamatan Java.
Shiro menjadikannya sangat mudah untuk membangunkan aplikasi yang cukup baik Ia boleh digunakan bukan sahaja dalam persekitaran JavaSE, tetapi juga dalam persekitaran JavaEE. Shiro boleh melakukan semuanya, pengesahan, kebenaran, penyulitan, pengurusan sesi, penyepaduan web, caching dan banyak lagi.
Pengesahan: pengesahan identiti, log masuk, sahkan sama ada pengguna mempunyai yang sepadan Identiti;
Kebenaran: kebenaran, iaitu, pengesahan kebenaran, mengesahkan sama ada pengguna yang disahkan mempunyai kebenaran tertentu, iaitu, menentukan sama ada pengguna boleh melakukan sebarang operasi, seperti: mengesahkan sama ada pengguna mempunyai peranan tertentu, atau berbutir halus Sahkan sama ada pengguna mempunyai kebenaran tertentu pada sumber tertentu!
Pengurus Sesi: Pengurusan sesi, iaitu, sesi pertama selepas pengguna log masuk dan sebelum keluar, semua maklumatnya ada dalam sesi; session can Ia adalah persekitaran JavaSE biasa, atau ia boleh menjadi persekitaran Web
Kriptografi: penyulitan untuk melindungi keselamatan data, seperti penyulitan kata laluan dan storan dalam pangkalan data dan bukannya storan teks biasa: Sokongan Web , yang boleh disepadukan dengan mudah ke dalam persekitaran Web;
Caching: Caching, contohnya, selepas pengguna log masuk, maklumat pengguna, peranan dan kebenarannya tidak perlu disemak setiap kali, yang boleh meningkatkan kecekapan
Concurrency: Shiro menyokong pengesahan serentak bagi aplikasi berbilang benang, iaitu, Jika anda membuka utas lain dalam satu utas, kebenaran boleh disebarkan secara automatik kepadanya
Pengujian: Berikan sokongan ujian
Jalankan Sebagai: Benarkan satu pengguna untuk berpura-pura menjadi pengguna lain (jika mereka membenarkannya) untuk mengakses;
Ingat Saya: Ingat saya, ini adalah fungsi yang sangat biasa, iaitu, selepas log masuk sekali, anda tidak perlu log masuk lain kali
Dari luar Shiro, iaitu, perhatikan cara menggunakan shiro untuk menyiapkan kerja dari perspektif aplikasi:
subjek: Objek yang berinteraksi secara langsung dengan kod aplikasi ialah Subjek, yang bermaksud teras API luaran Shiro ialah Subjek, Subjek mewakili pengguna semasa ini tidak semestinya orang tertentu aplikasi semasa ialah Subjek, seperti perangkak web, robot, dsb. Semua interaksi dengan Subjek akan diwakilkan kepada SecurityManager sebenarnya adalah Fasad, SecurityManageer ialah pelaksana sebenar
SecurityManager: Security Manager, iaitu, semua keselamatan-; operasi yang berkaitan akan berinteraksi dengan SecurityManager, dan ia menguruskan semua Subjek Ia dapat dilihat bahawa ia adalah teras Shiro dan bertanggungjawab untuk Berinteraksi dengan komponen Shiro yang lain, yang setara dengan peranan SpringMVC
DispatcherServlet
. Realm: Shiro memperoleh data keselamatan (seperti pengguna, peranan, kebenaran) daripada Realm, iaitu, SecurityManager ingin mengesahkan identiti pengguna, maka ia adalah perlu untuk mendapatkan pengguna yang sepadan daripada Realm untuk perbandingan untuk menentukan sama ada identiti pengguna adalah sah; ia juga perlu untuk mendapatkan peranan dan kebenaran pengguna yang sepadan daripada Realm untuk mengesahkan sama ada operasi pengguna boleh dijalankan sebagai Sumber Data
subjek: mana-mana 'pengguna' yang boleh berinteraksi dengan aplikasi itu; dikawal melalui Pengurus Keselamatan, yang menguruskan semua Subjek dan bertanggungjawab untuk pengesahan, kebenaran, sesi dan pengurusan cache
Realm: Boleh ada satu atau lebih alam, yang boleh dianggap sebagai sumber data entiti selamat, iaitu, digunakan untuk mendapatkan entiti selamat, yang boleh dilaksanakan menggunakan DBC atau memori, dsb., disediakan oleh pengguna, jadi secara amnya dalam aplikasi, anda perlu melaksanakan alam anda sendiri
SessionManager: komponen yang menguruskan kitaran hayat Sesi, dan Shiro bukan sahaja boleh digunakan dalam Persekitaran web, tetapi juga dalam persekitaran JavaSE biasa
CacheManager: Pengawal cache untuk menguruskan cache seperti pengguna, peranan, kebenaran, dll. kerana data ini jarang diakses, menambahkannya ke cache boleh meningkatkan prestasi akses
Kriptografi: modul kriptografi , Shiro telah menambah baik beberapa komponen penyulitan biasa untuk penyulitan kata laluan, penyahsulitan, dsb.
2. Mula Pantas
2. Buat projek Maven baharu, padamkan direktori srcnya dan gunakannya sebagai projek induk
3 Cipta modul Maven baharu dalam projek induk
4
<dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.1</version> </dependency> <!-- configure logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.29</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.29</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
5. Salin log4j.properties di bawah sumber dalam kes permulaan pantas
6. Salin fail shiro.ini
7 🎜>
8. Jalankan Quickstart.java 2. Analisis kodpublic class Quickstart { private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class); public static void main(String[] args) { //工厂模式,通过shiro.ini配置文件中的信息,生成一个工厂实例 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //获取当前的用户对象Subject Subject currentUser = SecurityUtils.getSubject(); //通过当前用户拿到session Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Subject=>session[" + value + "]"); } //判断当前的用户是否被认证 if (!currentUser.isAuthenticated()) { //Token :令牌,没有获取,随机 UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true); //设置记住我 try { currentUser.login(token); //执行了登录操作 } 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 (AuthenticationException ae) { //意外情况 ? 错误 ? } } //打印其标识主体(在这种情况下,为用户名) log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //测试角色是否存在 if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //粗粒度,极限范围小 //测试类型化的极限(不是实例级别) 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."); } //细粒度,极限范围广 //实例级别的权限(非常强大) 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!"); } //注销 currentUser.logout(); //退出 System.exit(0); } }3 >1. Tulis persekitaran ujian 1 Cipta modul springboot baharu dalam projek induk sebentar tadi
2 pakej penyepaduan
Berikut ialah tiga elemen utama untuk menulis fail konfigurasi
Shiro<!--SpringBoot 和 Shiro 整合包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>
Pengguna subjek-> ShiroFilterFactoryBean
Data sambungan realm
Tertib penciptaan objek dalam operasi sebenar: realm -> securityManager -> perlu mewarisi AuthorizingRealm
4 Cipta fail konfigurasi ShiroConfig baharu
5.//自定义的 UserRealm extends AuthorizingRealm public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //打印一个提示 System.out.println("执行了授权方法"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //打印一个提示 System.out.println("执行了认证方法"); return null; } }
@Configuration public class ShiroConfig { //ShiroFilterFactoryBean:3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebsecurityManager); return bean; } //DefaultWebSecurityManager:2 @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //关闭UserRealm securityManager.setRealm(userRealm); return securityManager; } //创建realm 对象,需要自定义类:1 @Bean(name="userRealm") public UserRealm userRealm(){ return new UserRealm(); } }
2 Gunakan
1. Pemintasan log masuk
Tambah permintaan log masuk yang perlu dipintas dalam kaedah getShiroFilterFactoryBean@Configuration public class ShiroConfig { //ShiroFilterFactoryBean:3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebsecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebsecurityManager); //添加shiro的内置过滤器 /* anon : 无需认证,就可以访问 authc : 必须认证了才能访问 user : 必须拥有 “记住我” 功能才能用 perms : 拥有对某个资源的权限才能访问 role : 拥有某个角色权限才能访问 */ filterMap.put("/user/add","authc"); filterMap.put("/user/update","authc"); //拦截 Map<String,String> filterMap=new LinkedHashMap<>(); filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); // //设置登录的请求 // bean.setLoginUrl("/toLogin"); return bean; }
2
1. Tulis kaedah log masuk dalam lapisan Pengawal
//登录的方法 @RequestMapping("/login") public String login(String username, String password, Model model) { //获取当前用户 Subject subject = SecurityUtils.getSubject(); //封装用户的登录数据,获得令牌 UsernamePasswordToken token = new UsernamePasswordToken(username, password); //登录 及 异常处理 try { //执行用户登录的方法,如果没有异常就说明OK了 subject.login(token); return "index"; } catch (UnknownAccountException e) { //如果用户名不存在 System.out.println("用户名不存在"); model.addAttribute("msg", "用户名错误"); return "login"; } catch (IncorrectCredentialsException ice) { //如果密码错误 System.out.println("密码错误"); model.addAttribute("msg", "密码错误"); return "login"; } } }
Ia boleh dilihat bahawa adat UserRealm dilaksanakan terlebih dahulu kaedah AuthenticationInfo, dan kemudian melakukan operasi berkaitan log masuk
3 Ubah suai kaedah doGetAuthenticationInfo dalam UserRealm
4 >
//认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //打印一个提示 System.out.println("执行了认证方法"); // 用户名密码 String name = "root"; String password = "123456"; //通过参数获取登录的控制器中生成的 令牌 UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; //用户名认证 if (!token.getUsername().equals(name)){ // return null UnKnownAccountException return null; } //密码认证, Shiro 自己做,为了避免和密码的接触 //最后返回一个 AuthenticationInfo 接口的实现类,这里选择 SimpleAuthenticationInfo // 三个参数:获取当前用户的认证 ; 密码 ; 认证名 return new SimpleAuthenticationInfo("", password, ""); } }Masukkan kata laluan yang betul untuk berjaya log masuk
4 Shiro mengintegrasikan Mybatis
1 >
2. Cipta aplikasi baharu.yml<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</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.1</version> </dependency>6 Tulis UserMapper
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 mybatis: type-aliases-package: com.huang.pojo mapper-locations: classpath:mybatis/mapper/*.xml7 Tulis UserMapper.xml
mybatis.type-aliases-package=com.longdi.pojo mybatis.mapper-locations=classpath:mapper/*.xml8 >
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency>Antara Muka Perkhidmatan Pengguna:
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; }9 Tulis kelas pelaksanaan antara muka UserServiceImpl
@Repository @Mapper public interface UserMapper { public User queryUserByName(String name); }10 Ujian dalam ShiroSpringbootApplicationTests1.>
<?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.longdi.mapper.UserMapper"> <select id="queryUserByName" resultType="User" parameterType="String"> select * from mybatis.user where name=#{name} </select> </mapper>1 sambung ke pangkalan data5. Laksanakan kebenaran permintaan 1 Ubah suai dalam kelas ShiroConfig
public interface UserService { public User queryUserByName(String name); }
@Service public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; @Override public User queryUserByName(String name) { return userMapper.queryUserByName(name); } }
2
@SpringBootTest class ShiroSpringbootApplicationTests { @Autowired UserServiceImpl userService; @Test void contextLoads() { System.out.println(userService.queryUserByName("longdi")); } }3 Log masuk untuk memintas kebenaran dan menguji dengan jayanya
4 kaedah doGetAuthorizationInfo
5. Minta ujian kebenaran berjaya
6 Shiro menyepadukan Thymeleaf
12. Integrasi ShiroDialect
3.index.html
<!--shiro和thymeleaf整合--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
5. Letakkan sesi
dalam pengesahan 6. Ubah suai index.html
Atas ialah kandungan terperinci Cara menggunakan rangka kerja keselamatan Apache Shiro dalam Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!