项目目录结构
1.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wpf</groupId>
<artifactId>shiro-springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</project>
2.application.yml
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_shiro?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
freemarker:
suffix: .html
cache: false
template-loader-path: classpath:/templates
mybatis:
#mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.wpf.pojo
configuration:
map-underscore-to-camel-case: true
3.3个实体类 用户,角色,权限
package com.wpf.pojo;
/**
* 用户
*/
public class User {
private Long id;
private String name;
private Integer password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPassword() {
return password;
}
public void setPassword(Integer password) {
this.password = password;
}
}
package com.wpf.pojo;
/**
* 角色
*/
public class Role {
private Long id;
private String roleName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
package com.wpf.pojo;
/**
* 权限
*/
public class Permission {
private Long id;
private String permission;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
}
4.dao层 3个对应实体类 用来查询用户,角色,和权限
@Repository
public interface UserDao {
@Select("select * from user where name = #{name}")
User findByName(String name);
}
@Repository
public interface RoleDao {
@Select("select * from role where user_id = #{id}")
List<Role> findByUserId(Long id);
}
@Repository
public interface PermissionDao {
@Select("select * from permission where role_id = #{id}")
List<Permission> findByRoleId(Long id);
}
5.自定义 Realm 用于测试直接调用了Dao层,跳过了service层,LoginService可替换为UserDao
//实现AuthorizingRealm接口用户用户认证
public class MyShiroRealm extends AuthorizingRealm {
//用于用户查询
@Autowired
private LoginServiceImpl loginService;
//用户角色查询
@Autowired
private RoleDao roleDao;
//用于权限查询
@Autowired
private PermissionDao permissionDao;
//角色权限和对应权限添加
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String name= (String) principalCollection.getPrimaryPrincipal();
//查询用户名称
User user = loginService.findByName(name);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//通过用户查寻角色
List<Role> roles = roleDao.findByUserId(user.getId());
for (Role role:roles) {
//添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
//通过角色查询权限
List<Permission> permissions = permissionDao.findByRoleId(role.getId());
for (Permission permission:permissions){
//添加角色权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
}
//用户认证
@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;
}
}
}
6.将自定义Realm配置进Shiro,配置过滤条件
@Configuration
public class ShiroConfiguration {
//将自己的验证方式加入容器
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map = new HashMap<String, String>();
//登出
map.put("/logout","logout");
//对所有用户认证
map.put("/**","authc");
//管理员,需要角色权限 “admin” 访问admin下面的路径需要admin角色
map.put("/admin/**", "roles[admin]");
//登录
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;
}
}
7.controller层 测试登录,退出,和权限
@Controller
public class LoginResource {
//进入登录页面
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(){
return "/logins";
}
//post登录
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public String login(String username,String password){
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
username,
password);
//进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
if(subject.hasRole("admin")){
System.out.println("admin角色");
}
if(subject.isPermitted("create")){
System.out.println("有create权限");
}
return "登录成功";
}
//跳转到主页
@RequestMapping(value = "/index")
public String index(){
return "indexx";
}
//退出登录
@RequestMapping(value = "/logout")
public String logout(){
return "logout";
}
//错误页面展示
@RequestMapping(value = "/error",method = RequestMethod.POST)
@ResponseBody
public String error(){
return "error ok!";
}
//注解的使用
@RequiresRoles("admin")
@RequiresPermissions("create")
@RequestMapping(value = "/create")
@ResponseBody
public String create(){
return "Create success!";
}
}
8.基本的登录,主页 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
主页
</body>
</html>
9.数据库数据
用户表
角色表
权限表
项目源码:https://download.csdn.net/download/weixin_42460179/10728459