一: 三个主要的概念
1.subject:当前用户(可以是使用者也可以是第三方服务,主要指一个正在与当前软件交互的东西),所有的Subject都需要SecurityManager
2.SecurityManager :安全管理员,Shiro架构的核心
3.Realms:用于进行权限信息的验证,可以由我们自己实现。在配置 Shiro 的时候,我们必须指定至少一个Realm 来实现认证(authentication)和/或授权(authorization)。
二:基本使用
1.导入依赖:
<!-- thymeleaf 与 shiro 整合-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--整合shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
2.配置类:
1)自定义一个Realm
public class UserRealm extends AuthorizingRealm {
@Autowired
UsersService usersService;
/**
* 授权
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 进入该方法说明已经通过认证了
// principalCollection 中可以获得认证中传入的三个参数
// 该数据就是认证时传入的用户信息
Users users = (Users) principalCollection.getPrimaryPrincipal();
// 也可以从Subject中获得当前用户的信息
// Subject subject = SecurityUtils.getSubject();
// Users user = (Users) subject.getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("user:add"); // 给当前用户授权,可从数据库中获取进行授权,此处为手动授权
return info;
}
/**
* 认证
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 可以获得表单中输入的用户名和密码
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
// 根据输入的用户名从数据库中查找该用户
Users users = usersService.queryUsersByUserName(userToken.getUsername());
if (users.getUsername() == null || !userToken.getUsername().equals(users.getUsername())) {
return null;// 自动抛出异常
}
// 密码认证不需要我们实现
return new SimpleAuthenticationInfo(users, users.getPassword(), users.getUsername());
// return new SimpleAuthenticationInfo("", users.getPassword(), "");
}
}
2)ShiroConfig 类
@Configuration
public class ShiroConfig {
/**
* 3 ShiroFilterFactoryBean
*
* @param defaultWebSecurityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全关联器
bean.setSecurityManager(defaultWebSecurityManager);
/**
* anon:无需认证就可以访问
* authc:必须认证了才能访问
* user:必须拥有 记住我 功能才能访问
* perms:拥有对某个资源的权限才能访问
* role:拥有某个介绍权限才能访问
*/
// 添加shiro 的内置过滤器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 授权
filterChainDefinitionMap.put("/add", "perms[user:add]");
filterChainDefinitionMap.put("/update", "authc");// 必须认证才能登录
// 配置退出
filterChainDefinitionMap.put("/logout", "logout");
// 设置登录请求
bean.setLoginUrl("/toLogin");
// 设置未授权
bean.setUnauthorizedUrl("/noauth");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}
/**
* 2 DefaultWebSecurityManager
*
* @param userRealm
* @return DefaultWebSecurityManager
*/
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 关联userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 1、创建Realm对象
*
* @return Realm 一个实例对象
*/
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
/**
* 创建ShiroDialect:用于整合shiro 和thymeleaf
*
* @return
*/
@Bean
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
}
3 control层
@RequestMapping("/login")
public String login(String username, String password, Model model) {
// 获取当前用户
Subject subject = SecurityUtils.getSubject();
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";
}
}
上述代码中用户的角色和权限信息没有从数据库中获取,都为自定义,可以修改这部分代码,将其改为从数据库中的获取。