Apache Shiro는 Java 보안(권한) 프레임워크입니다.
Shiro를 사용하면 JavaSE 환경뿐만 아니라 JavaEE 환경에서도 사용할 수 있는 충분한 애플리케이션을 매우 쉽게 개발할 수 있습니다. Shiro는 인증, 권한 부여, 암호화, 세션 관리, 웹 통합, 캐싱 등 모든 작업을 수행할 수 있습니다.
인증: 신원 인증, 로그인, 사용자가 해당 신원을 가지고 있는지 확인
인증: 승인, 즉 권한 확인, 인증된 사용자에게 특정 권한이 있는지 확인; 즉, 사용자가 특정 역할을 가지고 있는지 확인하거나 사용자가 특정 리소스에 대해 특정 권한을 가지고 있는지 세부적으로 확인하는 등 사용자가 수행할 수 있는 작업을 결정합니다.
세션 관리자: 세션 관리, 즉! , 사용자 로그인 후 첫 번째 세션입니다. 모든 정보는 세션에 있습니다. 세션은 일반 JavaSE 환경 또는 웹 환경일 수 있습니다.
암호화, 데이터 보안 보호; 비밀번호 암호화 일반 텍스트 대신 데이터베이스에 저장됨 웹 지원: 웹 환경에 쉽게 통합될 수 있음
캐싱: 예를 들어 사용자가 로그인한 후 사용자 정보, 역할 및 권한이 저장됩니다. 매번 확인할 필요가 없습니다. 이는 효율성을 향상시킬 수 있습니다
동시성: Shiro는 다중 스레드 응용 프로그램의 동시 확인을 지원합니다. 즉, 한 스레드에서 다른 스레드를 시작하면 권한이 자동으로 해당 스레드에 전파될 수 있습니다.
테스트: 테스트 제공 support;
다음 계정으로 실행: 사용자가 액세스를 다른 사용자로 가장하도록 허용합니다(허용하는 경우)
기억하기: 기억하세요. 이것은 매우 일반적인 기능입니다. 즉, 한 번 로그인한 후에는 그럴 필요가 없습니다. 다음에 로그인하세요
외부에서 Shiro를 바라보기, 즉 애플리케이션 관점에서 작업을 완료하기 위해 shiro를 사용하는 방법을 관찰하기:
제목: 애플리케이션이 수행하는 개체 즉, Shiro의 외부 API의 핵심은 주제이고 주제는 현재 사용자를 나타냅니다. 이 사용자는 웹 크롤러와 같이 반드시 특정 사람일 필요는 없습니다. Subject와의 모든 상호 작용은 SecurityManager에 위임됩니다. Subject는 실제로 Facade이고 SecurityManageer는 실제 실행자입니다.
SecurityManager: Security Manager, 즉 모든 보안 관련 작업은 SecurityManager와 상호 작용하고 모든 것을 관리합니다. Subjects Shiro의 핵심이며 Shiro의 다른 구성 요소와의 상호 작용을 담당한다고 볼 수 있습니다. 이는 SpringMVC의
DispatcherServlet
Realm의 역할과 동일합니다. Shiro는 보안 데이터(예: 사용자, 역할, 즉, SecurityManager가 사용자의 신원을 확인하려면 사용자의 신원이 합법적인지 확인하기 위해 Realm에서 해당 사용자를 가져와야 합니다. Realm에서 사용자의 작업을 수행할 수 있는지 확인하기 위한 권한입니다.
주제: 애플리케이션과 상호 작용하는 '사용자'; 관리자: SpringMVC의 DispatcherServlet과 동일하며 모든 특정 상호 작용은 보안 관리자를 통해 제어되며 인증, 승인 및 세션을 담당합니다. 주체 인증의 경우 확장 지점이며 사용자 정의할 수 있습니다. 즉, 어떤 상황에서 사용자 인증이 통과되는지 확인하는 데 사용됩니다. 주체가 해당 작업을 수행할 권한이 있는지 여부, 즉 사용자가 애플리케이션에서 액세스할 수 있는 기능을 제어합니다.
영역: 보안 엔터티 데이터 소스로 간주될 수 있는 하나 이상의 영역이 있을 수 있습니다. 보안 엔터티를 얻는 데 사용되는 것은 사용자가 제공하는 DBC 또는 메모리 구현 등을 사용하여 구현할 수 있으므로 일반적으로 애플리케이션에서는 자체 영역을 구현해야 합니다.
CacheManager: 사용자, 역할, 권한 등의 캐시를 관리하는 캐시 컨트롤러. 이러한 데이터는 기본적으로 거의 액세스할 수 없으므로 이후에 액세스가 향상될 수 있습니다.
암호화 모듈, Shiro는 비밀번호 암호화, 암호 해독 등을 위한 몇 가지 일반적인 암호화 구성 요소를 개선합니다.
2. 빠른 시작
1. 공식 웹사이트의 메시지를 따릅니다. 빠른 시작 사례 GitHub 주소를 찾으세요: shiro/samples/quickstart/
4. 빠른 시작 사례 POM을 XML 파일로 복사하세요
<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. 빠른 시작 사례의 리소스 아래에 log4j.properties를 복사합니다
6. shiro.ini 파일을 복사합니다
7. Quickstart.java
를 실행하고 시작합니다.2. 코드 분석
public 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); } }
<!--SpringBoot 和 Shiro 整合包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>
주제 사용자-> ShiroFilterFactoryBean
SecurityManager가 모든 사용자를 관리합니다-> DefaultWebSecurityManager
3. AuthorizingRealm
객체 생성 순서 실제 작업: realm -> securityManager -> subject
//自定义的 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; } }
4을 상속해야 하는 사용자 정의 영역을 작성합니다.
@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(); } }
5.
2.1. 로그인 차단 사용
@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; }
1. Controller 레이어에 로그인 메소드를 작성합니다
//登录的方法 @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"; } } }
3. UserRealm
//认证 @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, ""); } }
4에서 doGetAuthenticationInfo 메소드를 수정합니다. 테스트하고 잘못된 비밀번호를 입력합니다
올바른 비밀번호를 입력하면 로그인됩니다. 성공적으로4. Shiro는 Mybatis를 통합합니다.<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>
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/*.xml
4에서 새로운 application.yml을 생성합니다.
mybatis.type-aliases-package=com.longdi.pojo mybatis.mapper-locations=classpath:mapper/*.xml
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency>
3. 로그인하여 인증을 성공합니다.
4. 쓰기 인증 doGetAuthorizationInfo 메소드
5. 요청 인증 테스트 성공 6. Shiro가 Thymeleaf1 가져오기 종속성@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; }
5. index.html
을 수정하세요.
위 내용은 Java에서 Apache Shiro 보안 프레임워크를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!