1.首先创建一个普通的springboot项目。如何进行创建请百度一下
2.在pom文件中引用shiro相关的配置
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
3.该demo主要使用的是jpa来操作数据库,所以,不需要创建表,只是创建实体,就可以自动创建表了
(如有自己的权限配置表信息,请自己更改逻辑)
4.创建Entity实体类、DAO操作类、Service类
5.【重点】自定义权限检查和登录验证———-MyShiroRealm类
继承:AuthorizingRealm
注解:@Configuration
重写:doGetAuthorizationInfo方法(该方法主要是对于自己配置需要shiro权限控制的方法进行控制)
首先:加入数据库中的权限到SimpleAuthorizationInfo中
然后:shiro会根据加入的权限,判断是否有权限信息
doGetAuthenticationInfo方法(主要是登录的时候使用,进行验证的)
首先:我们会根据用户名去数据库里面获取用户信息
然后:加入到SimpleAuthenticationInfo权限中,进行判断
备注:这里面的逻辑,根据不同的需要进行配置
6.【重点】设置Shiro的配置———-ShiroConfiguration类
注解:@Configuration
核心点:主要是配置一个Bean的生成
主要Bean:
自定义权限验证和登录验证的Bean ------MyShiroRealm类
可以自定义密码比较器,因为有的密码我们可能是存在加盐、加密的,需要进行自定义,shiro是使用的是明文比较:CredentialsMatcher
配置权限管理的Bean,并且把自定义权限验证加入进去,这里可以加入cookie信息加入进去------------SecurityManager
SimpleCookie和CookieRememberMeManager都是用来做cookie的。详情请见demo。主要作用是进行“记住我”的这一项功能的开发
加入Shiro过滤器,用来进行监听(可以配置匿名访问、是否需要权限访问、认证失败的页面、认证成功的页面、登录页面)------------ShiroFilterFactoryBean
AuthorizationAttributeSourceAdvisor注解信息,配置该Bean主要是为了能够在springboot中使用注解
7.程序启动
8.检查方式:
先初始化用户、角色;进行登录是否验证通过;验证通过以后,访问需要验证的controller
9.controller中如何进行使用
demo中controller-------------------LoginResource中
@RequiresRoles("xxxx") 这里配置的是哪些角色可以使用
@RequiresPermissions("xxxxxxx")这里配置的是哪些权限可以使用
如果配置了一个,就按一个来进行判断
如果配置了两个,就按照两者结合来进行判断
这里的角色、权限,在哪儿加进去呢?----------第5步中。MyShiroRealm类类进行加入进去的。数据来源在哪儿呢?就是需要提供初始化数据进入数据库中或者配置文件中
代码块
MyShiroRealm
package com.example.shirotest.realm;
import com.example.shirotest.bean.Permission;
import com.example.shirotest.bean.Role;
import com.example.shirotest.bean.User;
import com.example.shirotest.service.ILoginService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 验证以及权限添加(自定义权限添加及检查)
* @author sy
*/
@Component
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
ILoginService loginService;
/**
* 添加权限(访问其他页面的时候进行权限判断
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String name= (String) principalCollection.getPrimaryPrincipal();
//查询用户名称(这里可以使用缓存来做),这里根据项目情况不同,选择不同的操作
User user = loginService.findByName(name);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Role role:user.getRoles()) {
//添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission:role.getPermissions()) {
//添加权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
}
/**
* 验证权限(登录的时候使用的)
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String name = authenticationToken.getPrincipal().toString();
User user = loginService.findByName(name);
if (user == null) {
//这里返回后会报出对应异常
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
}
}
ShiroConfiguration
package com.example.shirotest.realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import org.apache.shiro.mgt.SecurityManager;
/**
* shiro配置信息
*
* @author sy
*/
@Configuration
public class ShiroConfiguration {
private static final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);
/**
* 将自己的验证方式加入容器
* @param matcher
* @return
*/
@Bean
public MyShiroRealm myShiroRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(matcher);
return myShiroRealm;
}
/**
* 配置自定义的密码比较器
* @return
*/
@Bean(name = "credentialsMatcher")
public CredentialsMatcher credentialsMatcher() {
return new CredentialsMatcher();
}
/**
* 权限管理,配置主要是Realm的管理认证
*
* @return
*/
@Bean
public SecurityManager securityManager(@Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager,
CredentialsMatcher matcher) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm(matcher));
// 设置rememberMe管理器
securityManager.setRememberMeManager(cookieRememberMeManager);
return securityManager;
}
/**
* cookie对象;
*
* @return
*/
@Bean
public SimpleCookie rememberMeCookie() {
// 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// <!-- 记住我cookie生效时间30天(259200) ,单位秒;-->
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
/**
* 记住我管理器 cookie管理对象;
*
* @return
*/
@Bean(name = "cookieRememberMeManager")
public CookieRememberMeManager rememberMeManager() {
System.out.println("rememberMeManager()");
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
return cookieRememberMeManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> map = new HashMap<String, String>();
//表示可以匿名访问
map.put("/addUser", "anon");
map.put("/addRole", "anon");
//登出
map.put("/logout", "logout");
//对所有用户认证
map.put("/**", "authc");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//登录成功以后
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
/**
* 加入注解的使用,不加入这个注解不生效
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
CredentialsMatcher
package com.example.shirotest.realm;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
/**
* 自定义密码判断
* @author sy
*/
public class CredentialsMatcher extends SimpleCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken utoken=(UsernamePasswordToken) token;
//获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
String inPassword = new String(utoken.getPassword());
//获得数据库中的密码
String dbPassword=(String) info.getCredentials();
//进行密码的比对
return this.equals(inPassword, dbPassword);
}
}
实体表:
/**
* 权限
* @author
*/
@Entity
@Getter
@Setter
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String permission;
@ManyToOne(fetch = FetchType.EAGER)
private Role role;
}
/**
* 角色
* @author sy
*/
@Entity
@Getter
@Setter
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
@ManyToOne(fetch = FetchType.EAGER)
private User user;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
private List<Permission> permissions;
}
``/**
* 用户
* @author sy
*/
@Entity
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
private Integer password;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
private List<Role> roles;
}
**
controller配置
------------
**
package com.example.shirotest.controller;
import com.example.shirotest.bean.Role;
import com.example.shirotest.bean.User;
import com.example.shirotest.service.ILoginService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 登录测试
* @author sy
*/
@RestController
public class LoginResource {
@Autowired
private ILoginService loginService;
/**
* 退出的时候是get请求,主要是用于退出
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(){
return "login";
}
/**
* post登录
* @param map
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody Map map){
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
map.get("username").toString(),
map.get("password").toString());
//进行验证,这里可以捕获异常,然后返回对应信息
try {subject.login(usernamePasswordToken);
return "index";
} catch(Exception e) {
return "login";
}
}
@RequestMapping(value = "/index")
public String index(){
return "index";
}
/**
* 登出
* @return
*/
@RequestMapping(value = "/logout")
public String logout(){
return "logout";
}
/**
* 错误页面展示
* @return
*/
@RequestMapping(value = "/error",method = RequestMethod.POST)
public String error(){
return "error ok!";
}
/**
* 数据初始化
* @param map
* @return
*/
@RequestMapping(value = "/addUser")
public String addUser(@RequestBody Map<String,Object> map){
User user = loginService.addUser(map);
return "addUser is ok! \n" + user;
}
/**
* 角色初始化
* @param map
* @return
*/
@RequestMapping(value = "/addRole")
public String addRole(@RequestBody Map<String,Object> map){
Role role = loginService.addRole(map);
return "addRole is ok! \n" + role;
}
/**
* 自定义权限信息
* @param map
* @return
*/
@RequestMapping(value = "/addPermission")
public String addPermission(@RequestBody Map<String,Object> map){
Role role = loginService.addPermission(map);
return "addPermission is ok! \n" + role;
}
/**
* 注解的使用
* RequiresRoles表示数据库里面的角色名称,哪些角色可以使用
* RequiresPermissions表示数据库里面拥有哪些权限,哪些权限可以使用
*
* @return
*/
@RequiresRoles("admin")
@RequiresPermissions("create")
@RequestMapping(value = "/create")
public String create(){
return "Create success!";
}
/**
* 注解的使用
* RequiresRoles用来验证角色信息的
*RequiresPermissions是用来验证具体的权限的,可以使用addPermission来添加自定义
* @return
*/
@RequiresRoles("xxxx")
@RequiresPermissions("xxxxxxx")
@RequestMapping(value = "/cs")
public String cs(){
return "cs success!";
}
}
package com.example.shirotest.service;
import com.example.shirotest.bean.Permission;
import com.example.shirotest.bean.Role;
import com.example.shirotest.bean.User;
import com.example.shirotest.dao.PermissionRepository;
import com.example.shirotest.dao.RoleRepository;
import com.example.shirotest.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class LoginServiceImpl implements ILoginService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private PermissionRepository permissionRepository;
/**
* 添加用户
*
* @param map
* @return
*/
@Override
public User addUser(Map<String, Object> map) {
User user = new User();
user.setName(map.get("username").toString());
user.setPassword(Integer.valueOf(map.get("password").toString()));
userRepository.save(user);
return user;
}
/**
* 添加角色
*
* @param map
* @return
*/
@Override
public Role addRole(Map<String, Object> map) {
User userPro = new User();
userPro.setId(Long.valueOf(map.get("userId").toString()));
//将匹配对象封装成Example对象
Example example = Example.of(userPro);
User user = userRepository.findOne(example).get();
Role role = new Role();
role.setRoleName(map.get(“roleName”).toString());
role.setUser(user);
Permission permission1 = new Permission();
permission1.setPermission(“create”);
permission1.setRole(role);
Permission permission2 = new Permission();
permission2.setPermission(“update”);
permission2.setRole(role);
List permissions = new ArrayList<>();
permissions.add(permission1);
permissions.add(permission2);
role.setPermissions(permissions);
roleRepository.save(role);
return role;
}
/**
* 添加角色,并且自定义权限
*
* @param map
* @return
*/
@Override
public Role addPermission(Map<String, Object> map) {
Role rolePro = new Role();
rolePro.setId(Long.valueOf(map.get("roleId").toString()));
//将匹配对象封装成Example对象
Example example = Example.of(rolePro);
Role role = roleRepository.findOne(example).get();
Permission permission1 = new Permission();
permission1.setPermission(map.get(“permission”).toString());
permission1.setRole(role);
permissionRepository.save(permission1);
return role;
}
/**
* 查询用户通过用户名
*
* @param name
* @return
*/
@Override
public User findByName(String name) {
userRepository.findByPassword(12312312);
return userRepository.findByName(name);
}
}
package com.example.shirotest.service;
import com.example.shirotest.bean.Role;
import com.example.shirotest.bean.User;
import java.util.Map;
public interface ILoginService {
User addUser(Map<String, Object> map);
Role addRole(Map<String, Object> map);
User findByName(String name);
Role addPermission(Map<String, Object> map);
}
“`