maven依赖
<!--shiro相关配置-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- thymeleaf整合shiro标签 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
配置类
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro内置过滤器
/**
* Shiro内置过滤器,可以实现权限相关的拦截器
* 常用的过滤器:
* anon: 无需认证(登录)可以访问
* authc: 必须认证才可以访问
* user: 如果使用rememberMe的功能可以直接访问
* perms: 该资源必须得到资源权限才可以访问
* role: 该资源必须得到角色权限才可以访问
* logout:退出登陆
*/
Map<String, String> filtersMap=new LinkedHashMap<>();
filtersMap.put("/user/add","perms[user:add]");
filtersMap.put("/user/update","perms[user:update]");
filtersMap.put("/login","anon");
filtersMap.put("/logout","logout");
filtersMap.put("/user/login","anon");
filtersMap.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filtersMap);
//设置登录页面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//设置授权提示页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
/**
* 配置ShiroDialect,用于thymeleaf和shiro标签配合使用
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
Realm类
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private UserMapper userMapper;
/**
* 授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行授权");
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
//给用户添加权限
Subject subject = SecurityUtils.getSubject();
User principal = (User) subject.getPrincipal();
//String username = principal.getUsername();
//User user = userMapper.findUserByUsername(username);
//String permission = user.getPermission();
simpleAuthorizationInfo.addStringPermission(principal.getPermission());
return simpleAuthorizationInfo;
}
/**
* 认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行认证");
UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)token;
String username = usernamePasswordToken.getUsername();
User user = userService.findUserByUsername(username);
//判断用户名
if(user==null){
return null;
}
//判断密码
return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
}
}
html页面权限控制(thymeleaf)
xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
使用心得
shiro的配置类主要提供了对各种url的拦截,其中shiro为我们提供了几个常用的过滤器,通过这些过滤器我们可以对各种url进行不同程度的拦截:例如:对不重要的页面使用anon过滤器,对需要登录的进行authc过滤器进行拦截,等等。这些 shiro已经是实现好的 过滤器是shiro实现权限控制的基础。
除此之外,shiro的配置类还可以确定登录页面和未授权页面,以便可以对非法的访问进行一些页面跳转的处理。还需要在配置类中配置realm,realm需要用户自己定义,继承自AuthorizingRealm类。
对realm的理解:
可以认为他是shiro的dao层,在realm中有认证和授权两个功能(方法),我们可以在这里对用户执行认证和授权,分别在登录和需要进行权限验证是时候调用
- 一般,认证就将参数进行强转成包含用户填写用户名和密码的UsernamePasswordToken然后通过我们自己的dao方法判断用户身份,将判断结果返回,尤其重要的是对密码的判断不是由我们写代码判断,而是使用shiro提供的new SimpleAuthenticationInfo(user,user.getPassword(),getName()),三个参数分别是principal,用户真实密码,当前realm的名称。由shiro进行密码判断。
- 一般,授权就向用户添加权限字符串,与在shiroConfig配置的字符串保持一致,例如:simpleAuthorizationInfo.addStringPermission(“user:add” );
filtersMap.put("/user/add",“perms[user:add]”);
对shiroAPI的理解
我们使用subject和shiro进行交互
Subject subject = SecurityUtils.getSubject();
通常在处理登录逻辑和授权逻辑的时候需要使用
例如:登录逻辑
@RequestMapping("/login")
public String doLogin(@RequestParam("username")String username,
@RequestParam("password")String password,
Map map){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
subject.login(usernamePasswordToken);
} catch (UnknownAccountException e) {
e.printStackTrace();
map.put("msg","此账户不存在!");
return "login";
}catch (IncorrectCredentialsException e){
map.put("msg","密码错误");
return "login";
}
return "redirect:/hello";
}
授权逻辑
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行授权");
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
//给用户添加权限
Subject subject = SecurityUtils.getSubject();
User principal = (User) subject.getPrincipal();
//String username = principal.getUsername();
//User user = userMapper.findUserByUsername(username);
//String permission = user.getPermission();
simpleAuthorizationInfo.addStringPermission(principal.getPermission());
return simpleAuthorizationInfo;
}
最后
以后考虑学习spring security技术,听说比shiro更加强大,但是shiro更易用,所以更流行