Apache Shiro 是一个功能强大且易于使用的 Java 安全框架, 它为开发人员提供了一种直观, 全面的身份验证, 授权, 加密和会话管理解决方案. 下面是在 SpringBoot 中使用 Shiro 进行认证和授权的例子, 代码如下:
pom.xml
导入 SpringBoot 和 Shiro 依赖:
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring</artifactId>
- <version>1.4.2</version>
- </dependency>
- </dependencies>
也可以直接导入 Apache Shiro 提供的 starter:
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring-boot-Web-starter</artifactId>
- </dependency>
Shiro 配置类
- package com.cf.shiro1.config;
- import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
- import org.apache.shiro.realm.Realm;
- 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.HashMap;
- import java.util.Map;
- @Configuration
- public class ShiroConfig {
- @Bean
- public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
- ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
- // 设置安全管理器
- shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
- // 设置未认证 (登录) 时, 访问需要认证的资源时跳转的页面
- shiroFilterFactoryBean.setLoginUrl("/loginPage");
- // 设置访问无权限的资源时跳转的页面
- shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorizedPage");
- // 指定路径和过滤器的对应关系
- Map<String, String> filterMap = new HashMap<>();
- // 设置 / user/login 不需要登录就能访问
- filterMap.put("/user/login", "anon");
- // 设置 / user/list 需要登录用户拥有角色 user 时才能访问
- filterMap.put("/user/list", "roles[user]");
- // 其他路径则需要登录才能访问
- filterMap.put("/**", "authc");
- shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
- return shiroFilterFactoryBean;
- }
- @Bean
- public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("realm") Realm realm) {
- DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
- defaultWebSecurityManager.setRealm(realm);
- return defaultWebSecurityManager;
- }
- @Bean
- public Realm realm() {
- MyRealm realm = new MyRealm();
- // 使用 HashedCredentialsMatcher 带加密的匹配器来替换原先明文密码匹配器
- HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
- // 指定加密算法
- hashedCredentialsMatcher.setHashAlgorithmName("MD5");
- // 指定加密次数
- hashedCredentialsMatcher.setHashIterations(3);
- realm.setCredentialsMatcher(hashedCredentialsMatcher);
- return realm;
- }
- }
自定义 Realm
- package com.cf.shiro1.config;
- import org.apache.shiro.authc.*;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.authz.SimpleAuthorizationInfo;
- import org.apache.shiro.crypto.hash.SimpleHash;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.util.ByteSource;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Set;
- public class MyRealm extends AuthorizingRealm {
- /**
- * 授权
- *
- * @param principalCollection
- * @return
- */
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
- Object username = principalCollection.getPrimaryPrincipal();
- SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
- simpleAuthorizationInfo.setRoles(getRoles(username.toString()));
- return simpleAuthorizationInfo;
- }
- /**
- * 认证
- *
- * @param authenticationToken
- * @return
- * @throws AuthenticationException
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
- UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
- String username = token.getUsername();
- Map<String, Object> userInfo = getUserInfo(username);
- if (userInfo == null) {
- throw new UnknownAccountException();
- }
- // 盐值, 此处使用用户名作为盐
- ByteSource salt = ByteSource.Util.bytes(username);
- SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, userInfo.get("password"), salt, getName());
- return authenticationInfo;
- }
- /**
- * 模拟数据库查询, 通过用户名获取用户信息
- *
- * @param username
- * @return
- */
- private Map<String, Object> getUserInfo(String username) {
- Map<String, Object> userInfo = null;
- if ("zhangsan".equals(username)) {
- userInfo = new HashMap<>();
- userInfo.put("username", "zhangsan");
- // 加密算法, 原密码, 盐值, 加密次数
- userInfo.put("password", new SimpleHash("MD5", "123456", username, 3));
- }
- return userInfo;
- }
- /**
- * 模拟查询数据库, 获取用户角色列表
- *
- * @param username
- * @return
- */
- private Set<String> getRoles(String username) {
- Set<String> roles = new HashSet<>();
- roles.add("user");
- roles.add("admin");
- return roles;
- }
- }
- Controller
- package com.cf.shiro1.controller;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.*;
- import org.apache.shiro.subject.Subject;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RestController;
- @RestController
- @RequestMapping("/user")
- public class UserController {
- /**
- * 登录
- * @param username
- * @param password
- * @return
- */
- @RequestMapping("/login")
- public String userLogin(String username, String password) {
- String result;
- // 获取当前用户
- Subject currentUser = SecurityUtils.getSubject();
- // 用户是否已经登录, 未登录则进行登录
- if (!currentUser.isAuthenticated()) {
- // 封装用户输入的用户名和密码
- UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
- try {
- // 登录, 进行密码比对, 登录失败时将会抛出对应异常
- currentUser.login(usernamePasswordToken);
- result = "登录成功";
- } catch (UnknownAccountException uae) {
- result = "用户名不存在";
- } catch (IncorrectCredentialsException ice) {
- result = "密码错误";
- } catch (LockedAccountException lae) {
- result = "用户状态异常";
- } catch (AuthenticationException ae) {
- result = "登录失败, 请与管理员联系";
- }
- } else {
- result = "您已经登录成功了";
- }
- return result;
- }
- @RequestMapping("/list")
- public String userList() {
- return "访问我需要登录并且需要拥有 user 角色!";
- }
- }
使用 Shiro 实现认证和授权(基于 SpringBoot)
来源: http://www.bubuko.com/infodetail-3398795.html