怎样定制shiro框架认证流程

avatar
作者
筋斗云
阅读量:0

Apache Shiro 是一个强大且灵活的 Java 安全框架,用于身份验证、授权、加密和会话管理。要定制 Shiro 的认证流程,你需要遵循以下步骤:

1. 引入依赖

首先,在你的项目中引入 Apache Shiro 的依赖。如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖:

<dependency>     <groupId>org.apache.shiro</groupId>     <artifactId>shiro-core</artifactId>     <version>1.8.0</version> </dependency> <dependency>     <groupId>org.apache.shiro</groupId>     <artifactId>shiro-spring</artifactId>     <version>1.8.0</version> </dependency> 

2. 配置 Shiro

创建一个 Shiro 配置类,通常命名为 ShiroConfig。在这个类中,你需要配置 Shiro 的各个组件,包括 SecurityManagerRealmAuthenticatorAuthorizerSessionManager

import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.jdbc.JdbcRealm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  @Configuration public class ShiroConfig {      @Bean     public DefaultWebSecurityManager securityManager() {         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();         securityManager.setRealm(jdbcRealm());         return securityManager;     }      @Bean     public JdbcRealm jdbcRealm() {         JdbcRealm jdbcRealm = new JdbcRealm();         // 配置数据源         jdbcRealm.setDataSource(dataSource());         // 配置 SQL 语句         jdbcRealm.setConnectionCheckSQL("SELECT 1");         jdbcRealm.setPermissionsLookupEnabled(true);         return jdbcRealm;     }      @Bean     public DataSource dataSource() {         // 配置数据源,例如使用 HikariCP         HikariDataSource dataSource = new HikariDataSource();         dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");         dataSource.setUsername("username");         dataSource.setPassword("password");         return dataSource;     }      @Bean     public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();         shiroFilterFactoryBean.setSecurityManager(securityManager);          // 配置过滤器链         Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();         filterChainDefinitionMap.put("/admin/**", "authc"); // 需要认证的路由         filterChainDefinitionMap.put("/**", "anon"); // 不需要认证的路由         shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);          return shiroFilterFactoryBean;     } } 

3. 自定义 Realm

在上面的配置中,JdbcRealm 是用于从数据库中获取用户信息和权限的。你可以通过继承 AuthorizingRealm 来实现自定义的认证和授权逻辑。

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 java.util.HashSet; import java.util.Set;  public class CustomRealm extends AuthorizingRealm {      @Override     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {         String username = (String) principals.getPrimaryPrincipal();         // 查询用户的角色和权限         Set<String> roles = getRolesForUser(username);         Set<String> permissions = getPermissionsForUser(username);          SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();         authorizationInfo.setRoles(roles);         authorizationInfo.setStringPermissions(permissions);         return authorizationInfo;     }      @Override     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {         UsernamePasswordToken upToken = (UsernamePasswordToken) token;         String username = upToken.getUsername();          // 查询用户信息         User user = getUserByUsername(username);         if (user == null) {             throw new UnknownAccountException("用户不存在");         }          return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());     }      private Set<String> getRolesForUser(String username) {         // 实现获取用户角色的逻辑         return new HashSet<>();     }      private Set<String> getPermissionsForUser(String username) {         // 实现获取用户权限的逻辑         return new HashSet<>();     }      private User getUserByUsername(String username) {         // 实现从数据库中获取用户的逻辑         return new User();     } } 

4. 自定义过滤器

Shiro 允许你自定义过滤器来实现特定的认证流程。你可以通过继承 org.apache.shiro.web.filter.authc.AuthenticatingFilter 来实现自定义的过滤器。

import org.apache.shiro.authc.*; import org.apache.shiro.web.filter.authc.AuthenticatingFilter;  import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException;  public class CustomAuthenticatingFilter extends AuthenticatingFilter {      @Override     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {         String username = getUsername(request);         String password = getPassword(request);         return new UsernamePasswordToken(username, password);     }      @Override     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {         return executeLogin(request, response);     }      @Override     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {         return false;     }      @Override     protected void executeLogin(ServletRequest request, ServletResponse response) throws Exception {         try {             getSubject(request, response).login(createToken(request, response));         } catch (AuthenticationException e) {             // 处理认证失败的情况             response.setContentType("application/json;charset=UTF-8");             response.getWriter().write("{\"status\":\"error\",\"message\":\"认证失败\"}");         }     } } 

然后在 ShiroFilterFactoryBean 中配置这个自定义过滤器:

@Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {     ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();     shiroFilterFactoryBean.setSecurityManager(securityManager);      // 配置过滤器链     Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();     filterChainDefinitionMap.put("/admin/**", "customAuthc"); // 使用自定义过滤器     filterChainDefinitionMap.put("/**", "anon"); // 不需要认证的路由     shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);      return shiroFilterFactoryBean; } 

5. 自定义认证逻辑

CustomAuthenticatingFilter 中,你可以实现自定义的认证逻辑,例如添加额外的验证步骤、处理不同的认证方式(如短信验证码、邮箱验证等)。

通过以上步骤,你可以定制 Shiro 的认证流程,以满足你的项目需求。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!