标签:签名 启动 作用 被锁 识别 component 会话管理 http doc
Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密。
Apache Shiro的首要目标是易于使用和理解。安全通常很复杂,甚至让人感到很痛苦,但是Shiro却不是这样子的。一个好的安全框架应该屏蔽复杂性,向外暴露简单、直观的API,来简化开发人员实现应用程序安全所花费的时间和精力。
Shiro能做什么呢?
等等——都集成到一个有凝聚力的易于使用的API。
Shiro 致力在所有应用环境下实现上述功能,小到命令行应用程序,大到企业应用中,而且不需要借助第三方框架、容器、应用服务器等。当然 Shiro 的目的是尽量的融入到这样的应用环境中去,但也可以在它们之外的任何环境下开箱即用。
Apache Shiro是一个全面的、蕴含丰富功能的安全框架。下图为描述Shiro功能的框架图:
Authentication(认证), Authorization(授权), Session Management(会话管理), Cryptography(加密)被 Shiro 框架的开发团队称之为应用安全的四大基石。那么就让我们来看看它们吧:
还有其他的功能来支持和加强这些不同应用环境下安全领域的关注点。特别是对以下的功能支持:
注意: Shiro不会去维护用户、维护权限,这些需要我们自己去设计/提供,然后通过相应的接口注入给Shiro
在概念层,Shiro 架构包含三个主要的理念:Subject,SecurityManager和 Realm。下面的图展示了这些组件如何相互作用,我们将在下面依次对其进行描述。
我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
新建一个工程
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--Shiro依赖--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> <version>1.9.22</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> </dependencies>
实体类的创建 是jpa形式的
package com.shiro.shiro.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import java.io.Serializable; import java.util.List; /** * @Author zly * @Date 2018/11/8 14:19 */ @Entity public class SysPermission implements Serializable { @Id@GeneratedValue private Integer id;//主键. private String name;//名称. @Column(columnDefinition="enum(‘menu‘,‘button‘)") private String resourceType;//资源类型,[menu|button] private String url;//资源路径. private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view private Long parentId; //父编号 private String parentIds; //父编号列表 private Boolean available = Boolean.FALSE; @ManyToMany @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")}) private List<SysRole> roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getResourceType() { return resourceType; } public void setResourceType(String resourceType) { this.resourceType = resourceType; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } public Long getParentId() { return parentId; } public void setParentId(Long parentId) { this.parentId = parentId; } public String getParentIds() { return parentIds; } public void setParentIds(String parentIds) { this.parentIds = parentIds; } public Boolean getAvailable() { return available; } public void setAvailable(Boolean available) { this.available = available; } public List<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } }
UserInfo.java
package com.shiro.shiro.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import java.io.Serializable; import java.util.List; /** * @Author zly * @Date 2018/11/8 14:04 */ @Entity public class UserInfo implements Serializable { @Id @GeneratedValue private Integer uid; @Column(unique =true) private String username;//帐号 private String name;//名称(昵称或者真实姓名,不同系统不同定义) private String password; //密码; private String salt;//加密密码的盐 private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定. @ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据; @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") }) private List<SysRole> roleList;// 一个用户具有多个角色 public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } public byte getState() { return state; } public void setState(byte state) { this.state = state; } public List<SysRole> getRoleList() { return roleList; } public void setRoleList(List<SysRole> roleList) { this.roleList = roleList; } /** * 密码盐. * @return */ public String getCredentialsSalt(){ return this.username+this.salt; } //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解 }
SysRole.java
package com.shiro.shiro.entity; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import java.util.List; /** * @Author zly * @Date 2018/11/8 14:11 */ @Entity public class SysRole { @Id@GeneratedValue private Integer id; // 编号 private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的: private String description; // 角色描述,UI界面显示使用 private Boolean available = Boolean.FALSE; // 是否可用,如果不可用将不会添加给用户 //角色 -- 权限关系:多对多关系; @ManyToMany(fetch= FetchType.EAGER) @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")}) private List<SysPermission> permissions; // 用户 - 角色关系定义; @ManyToMany @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")}) private List<UserInfo> userInfos;// 一个角色对应多个用户 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Boolean getAvailable() { return available; } public void setAvailable(Boolean available) { this.available = available; } public List<SysPermission> getPermissions() { return permissions; } public void setPermissions(List<SysPermission> permissions) { this.permissions = permissions; } public List<UserInfo> getUserInfos() { return userInfos; } public void setUserInfos(List<UserInfo> userInfos) { this.userInfos = userInfos; } }
配置ShiroConfig
package com.shiro.shiro.config; import com.shiro.shiro.realm.MyShiroRealm; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; /** * @Author zly * @Date 2018/11/8 14:33 */ @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){ System.out.println("进入了filter"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("/static/**","anno"); linkedHashMap.put("/logout","logout"); ////<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; // //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> linkedHashMap.put("/**","authc"); shiroFilterFactoryBean.setLoginUrl("/login"); //成功之后访问的页面 shiroFilterFactoryBean.setSuccessUrl("/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(linkedHashMap); return shiroFilterFactoryBean; } @Bean public MyShiroRealm myshiroRealm(){ MyShiroRealm realm=new MyShiroRealm(); return realm; } @Bean public SecurityManager securityManager(){ DefaultSecurityManager securityManager = new DefaultSecurityManager(); securityManager.setRealm(myshiroRealm()); return securityManager; } }
自定义realm MyRealm
package com.shiro.shiro.realm; import com.shiro.shiro.entity.SysPermission; import com.shiro.shiro.entity.SysRole; import com.shiro.shiro.entity.UserInfo; import com.shiro.shiro.service.UserInfoService; 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.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * @Author zly * @Date 2018/11/8 14:45 */ public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserInfoService userInfoService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) { System.out.println("到了权限配置"); SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo(); UserInfo userInfo = (UserInfo)principal.getPrimaryPrincipal(); for (SysRole sysRole : userInfo.getRoleList()) { authorizationInfo.addRole(sysRole.getRole()); for (SysPermission sysPermission : sysRole.getPermissions()) { authorizationInfo.addStringPermission(sysPermission.getPermission()); } } return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("进入了shiro验证"); String username = (String)token.getPrincipal(); System.out.println("获取到的签名是:"+token.getPrincipal()); UserInfo userInfo = userInfoService.findByUserName(username); System.out.println("用户信息:"+userInfo); if (userInfo==null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userInfo,userInfo.getPassword(), ByteSource.Util.bytes(userInfo.getCredentialsSalt()),getName()); return authenticationInfo; } }
dao
package com.shiro.shiro.dao; import com.shiro.shiro.entity.UserInfo; import org.springframework.data.repository.CrudRepository; /** * @Author zly * @Date 2018/11/8 14:54 */ public interface UserInfoDao extends CrudRepository<UserInfo,Long>{ UserInfo findByUsername(String username); }
service
package com.shiro.shiro.service; import com.shiro.shiro.entity.UserInfo; /** * @Author zly * @Date 2018/11/8 14:59 */ public interface UserInfoService { UserInfo findByUserName(String username); }
Impl
package com.shiro.shiro.service.impl; import com.shiro.shiro.dao.UserInfoDao; import com.shiro.shiro.entity.UserInfo; import com.shiro.shiro.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @Author zly * @Date 2018/11/8 15:00 */ @Service public class UserInfoServiceImpl implements UserInfoService { @Autowired private UserInfoDao userInfoDao; @Override public UserInfo findByUserName(String username) { return userInfoDao.findByUsername(username); } }
UserInfoController
package com.shiro.shiro.controller; import com.shiro.shiro.service.UserInfoService; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @Author zly * @Date 2018/11/8 15:20 */ @Controller @RequestMapping("/userInfo") public class UserInfoController { @Autowired private UserInfoService userInfoService; @RequestMapping("/userList") @RequiresPermissions("userInfo:view")//权限管理 public String userInfo(){ return "userInfo"; } @RequestMapping("/userAdd") @RequiresPermissions("userInfo:add") public String addUser(){ return "userInfoAdd"; } @RequestMapping("userDel") @RequiresPermissions("userInfo:del") public String del(){ return "userInfoDel"; } }
HomeController
package com.shiro.shiro.controller; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * @Author zly * @Date 2018/11/8 15:34 */@Controller public class HomeContorller { @RequestMapping({"/","/index"}) public String index(){ return "index"; } @RequestMapping("/login") public String login(HttpServletRequest request, Map<String,Object> map){ System.out.println("进入了登录操作"); String faile = (String)request.getAttribute("shiroLoginFaile"); System.out.println("faile"+faile); String msg=""; if (faile!=null){ if(UnknownAccountException.class.getTypeName().equals(faile)){ System.out.println("账号不存在"); msg="账号不存在"; }else if (IncorrectCredentialsException.class.getTypeName().equals(faile)){ System.out.println("密码错误"); msg="密码错误"; }else if ("KaptchaValidateFailed".equals(faile)){ System.out.println("验证码错误"); msg="验证码错误"; }else { msg=faile; System.out.println(faile); } } map.put("msg", msg); // 此方法不处理登录成功,由shiro进行处理 return "/login"; } @RequestMapping("/403") public String unauthorizedRole(){ System.out.println("------没有权限-------"); return "403"; } }
页面贴一下登录界面
login.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Login</title> </head> <body> 错误信息:<h4 th:text="${msg}"></h4> <form action="" method="post"> <p>账号:<input type="text" name="username" value="admin"/></p> <p>密码:<input type="text" name="password" value="123456"/></p> <p><input type="submit" value="登录"/></p> </form> </body> </html>
yml配置文件
spring:
datasource:
username: root
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://99.48.232.39:3306/boot?characterEncoding=utf8
password: 1qaz@WSX
hikari:
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
jpa:
database: mysql
show-sql: true
hibernate:
ddl-auto: update
naming:
strategy: org.hibernate.cfg.DefaultComponentSafeNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
thymeleaf:
cache: false
mode: LEGACYHTML5
最后看一下项目目录
启动项目登录访问
标签:签名 启动 作用 被锁 识别 component 会话管理 http doc
原文地址:https://www.cnblogs.com/blackCatFish/p/9929787.html