SpringBoot学习-简单shiro权限控制
来源:互联网 发布:淘宝买家真实福利图 编辑:程序博客网 时间:2024/06/06 05:38
前面介绍了很多基础设置的搭建方法,现在在前面的基础上,我们利用shiro来实现简单的登录及权限控制(只是简单的shiro集成,更细颗粒的shiro权限控制方法可以自己去学习shiro相关功能实现)。
框架基础:前面搭建的基础框架SpringBoot+JPA+MySQL
第一步:maven引入Jar包
<!-- shiro权限控制框架 --><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version></dependency>
第二步:前端登录页设计及方法
登录页代码就不贴了,自己弄个简单的登录页测试一下就行
第三步:后端设计
Shiro配置类:
package com.example.demo.shiro;import org.apache.shiro.authc.credential.CredentialsMatcher;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap;import java.util.Map;/** * Created by John.Zhang on 2017/10/10. */@Configurationpublic class ShiroConfig { /** * ShiroFilterFactoryBean 处理拦截资源文件问题。 * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在 * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager * * Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过 * 3、部分过滤器可指定参数,如perms,roles * */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/"); // 未授权界面;// shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 拦截器. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); System.out.println("Shiro拦截器工厂类注入成功"); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 设置realm. securityManager.setRealm(myShiroRealm()); return securityManager; } /** * 身份认证realm; * * @return */ @Bean public ShiroRealm myShiroRealm() { ShiroRealm myShiroRealm = new ShiroRealm(); myShiroRealm.setCredentialsMatcher(credentialsMatcher()); return myShiroRealm; } /** * 凭证匹配器(用于加密密码使用,如不需要可以去除相关信息) */ @Bean public CredentialsMatcher credentialsMatcher(){ HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher("MD5"); credentialsMatcher.setHashIterations(2); return credentialsMatcher; }}
自定义认证:
package com.example.demo.shiro;import com.example.demo.entities.Permission;import com.example.demo.entities.Role;import com.example.demo.entities.User;import com.example.demo.service.UserSevice;import org.apache.shiro.authc.*;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.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import java.util.ArrayList;import java.util.List;public class ShiroRealm extends AuthorizingRealm { private Logger logger = LoggerFactory.getLogger(ShiroRealm.class); @Autowired private UserSevice userSevice; /** * 登录认证 * * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; logger.info("验证当前Subject时获取到token为:" + token.toString()); //查出是否有此用户 User hasUser = userSevice.findByName(token.getUsername()); if (hasUser != null) { if(hasUser.getIsLocked() != null && hasUser.getIsLocked().equals(User.IsLocked.LOCKED)) { throw new LockedAccountException("用户已被锁定,无法登录"); } List<Role> rlist = userSevice.findRolesByUid(hasUser.getId());//获取用户角色 List<Permission> plist = userSevice.findPermissionsByUid(hasUser.getId());//获取用户权限 List<String> roles = new ArrayList<>(); List<String> permissions = new ArrayList<>(); for(Role role : rlist){ roles.add(role.getName()); } for(Permission permission : plist){ permissions.add(permission.getName()); } hasUser.setRoleList(roles); hasUser.setPermissionList(permissions);// Session session = SecurityUtils.getSubject().getSession();// session.setAttribute("user", hasUser);//成功则放入session // 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验 return new SimpleAuthenticationInfo(hasUser, hasUser.getPassword(),ByteSource.Util.bytes(hasUser.getSalt()), getName()); }else { throw new UnknownAccountException("用户不存在"); } } /** * 权限认证 * * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("##################执行Shiro权限认证##################"); User user = (User) principalCollection.getPrimaryPrincipal();// //到数据库查是否有此对象// User user = null;// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法// user = userMapper.findByName(loginName); if (user != null) { //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission) SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //用户的角色集合 info.addRoles(user.getRoleList()); //用户的权限集合 info.addStringPermissions(user.getPermissionList()); return info; } // 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址 return null; }}
用户实体类User:
package com.example.demo.entities;import org.hibernate.annotations.GenericGenerator;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedDate;import javax.persistence.*;import java.util.Date;import java.util.List;import java.util.Random;import java.util.UUID;import static javax.persistence.GenerationType.TABLE;import static javax.persistence.TemporalType.TIMESTAMP;@Entity@Table(name = "tab_user")public class User extends CommEntity{ @Id @Column(name = "user_id") @GeneratedValue(strategy = TABLE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "segment_value", value = "user"), @org.hibernate.annotations.Parameter(name = "increment_size", value = "100"), @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled") }) private Long id; @Column(name = "user_name",nullable = false,unique = true) private String name; @Column(name = "password",nullable = false) private String password; @Column(name = "user_salt",nullable = false) private String salt = UUID.randomUUID().toString(); @Column(name = "user_status") private Integer status = 1; @Column(name = "is_locked") private IsLocked isLocked = IsLocked.LOCKED; @Transient private List<String> roleList; @Transient private List<String> permissionList; 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 String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public List<String> getRoleList() { return roleList; } public void setRoleList(List<String> roleList) { this.roleList = roleList; } public List<String> getPermissionList() { return permissionList; } public void setPermissionList(List<String> permissionList) { this.permissionList = permissionList; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } public IsLocked getIsLocked() { return isLocked; } public void setIsLocked(IsLocked isLocked) { this.isLocked = isLocked; } public static enum IsLocked{ LOCKED("锁定"),UNLOCKED("正常"); IsLocked(String type){ this.type = type; } private String type; public String getType() { return type; } public void setType(String type) { this.type = type; } public static IsLocked getValue(Integer i){ switch (i){ case 0: return LOCKED; case 1: return UNLOCKED; default: return null; } } }}
角色实体类Role:
package com.example.demo.entities;import org.hibernate.annotations.GenericGenerator;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedDate;import javax.persistence.*;import java.util.Date;import java.util.List;import static javax.persistence.GenerationType.TABLE;import static javax.persistence.TemporalType.TIMESTAMP;/** * Created by John.Zhang on 2017/10/11. */@Entity@Table(name = "tab_sys_role")public class Role extends CommEntity{ @Id @Column(name = "role_id") @GeneratedValue(strategy = TABLE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "segment_value", value = "role"), @org.hibernate.annotations.Parameter(name = "increment_size", value = "1"), @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled") }) private Long id; @Column(name = "role_name",unique = true,nullable = false) private String name; @Column(name = "role_type",nullable = false) private Short type; @Transient private List<Permission> permissionList; 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 Short getType() { return type; } public void setType(Short type) { this.type = type; } public List<Permission> getPermissionList() { return permissionList; } public void setPermissionList(List<Permission> permissionList) { this.permissionList = permissionList; }}
用户角色映射类UserRole:
package com.example.demo.entities;import org.hibernate.annotations.GenericGenerator;import javax.persistence.*;import static javax.persistence.GenerationType.TABLE;/** * Created by John.Zhang on 2017/10/11. */@Entity@Table(name = "tab_user_role")public class UserRole extends CommEntity{ @Id @Column(name = "user_role_id") @GeneratedValue(strategy = TABLE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "segment_value", value = "user_role"), @org.hibernate.annotations.Parameter(name = "increment_size", value = "1"), @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled") }) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "role_id") private Role role; @Column(name = "note") private String note; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } public String getNote() { return note; } public void setNote(String note) { this.note = note; }}
权限基础类Permission:
package com.example.demo.entities;import org.hibernate.annotations.GenericGenerator;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedDate;import javax.persistence.*;import java.util.Date;import static javax.persistence.GenerationType.TABLE;import static javax.persistence.TemporalType.TIMESTAMP;/** * Created by John.Zhang on 2017/10/11. */@Entity@Table(name = "tab_sys_permission")public class Permission extends CommEntity{ @Id @Column(name = "permission_id") @GeneratedValue(strategy = TABLE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "segment_value", value = "permission"), @org.hibernate.annotations.Parameter(name = "increment_size", value = "1"), @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled") }) private Long id; @Column(name = "permission_name",unique = true,nullable = false) private String name; @Column(name = "permission_url") private String url; 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 String getUrl() { return url; } public void setUrl(String url) { this.url = url; }}
角色权限映射类RolePermission:
package com.example.demo.entities;import org.hibernate.annotations.GenericGenerator;import javax.persistence.*;import static javax.persistence.GenerationType.TABLE;/** * Created by John.Zhang on 2017/10/11. */@Entity@Table(name = "tab_role_permission")public class RolePermission extends CommEntity{ @Id @Column(name = "role_permission_id") @GeneratedValue(strategy = TABLE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "segment_value", value = "role_permission"), @org.hibernate.annotations.Parameter(name = "increment_size", value = "1"), @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled") }) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "role_id") private Role role; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "permission_id") private Permission permission; @Column(name = "note") private String note; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } public Permission getPermission() { return permission; } public void setPermission(Permission permission) { this.permission = permission; } public String getNote() { return note; } public void setNote(String note) { this.note = note; }}
公用实体类CommEntity:
package com.example.demo.entities;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedDate;import javax.persistence.Column;import javax.persistence.Temporal;import java.util.Date;import static javax.persistence.TemporalType.TIMESTAMP;/** * Created by John.Zhang on 2017/10/11. */public class CommEntity { @CreatedDate @Temporal(TIMESTAMP) @Column(name = "create_time") private Date createTime = new Date(); @LastModifiedDate @Temporal(TIMESTAMP) @Column(name = "modified_date") private Date modifiedDate; public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getModifiedDate() { return modifiedDate; } public void setModifiedDate(Date modifiedDate) { this.modifiedDate = modifiedDate; }}
登录Controller :
package com.example.demo.controller;import com.example.demo.entities.User;import com.example.demo.entities.UserToken;import com.example.demo.service.UserSevice;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;/** * Created by John.Zhang on 2017/10/9. */@RestControllerpublic class LoginController { @Autowired private UserSevice userSevice; @PostMapping(value = "login") public HashMap<String,Object> login(@RequestBody UserToken userToken){ return userSevice.login(userToken); } @PostMapping(value = "getLoginUser") public User getLoginUser(){ return userSevice.getLoginUser(); }}
路径跳转Controller :
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/** * Created by John.Zhang on 2017/10/9. */@Controllerpublic class PathController { private String LoginPath = "Login"; private String IndexPath = "index"; @RequestMapping(value = "/") public String loginInit(){ return LoginPath; } @RequestMapping(value = "index") public String toIndex(){ return IndexPath; }}
方法实现类(接口类不贴了,自动生成就行):
package com.example.demo.service.impl;import com.example.demo.entities.*;import com.example.demo.repository.*;import com.example.demo.service.UserSevice;import com.example.demo.utils.DataTransUtil;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.HashMap;import java.util.List;/** * Created by John.Zhang on 2017/10/9. */@Servicepublic class UserSeviceImpl implements UserSevice{ @Autowired private UserRepository userRepository; @Autowired private UserRoleRepository userRoleRepository; @Autowired private RolePermissionRepository rolePermissionRepository; @Autowired private RoleRepository roleRepository; @Autowired private PermissionRepository permissionRepository; @Override public HashMap<String, Object> login(UserToken userToken) { UsernamePasswordToken token = new UsernamePasswordToken(userToken.getUsername(), userToken.getPassword()); try { SecurityUtils.getSubject().login(token); }catch (UnknownAccountException e){ return DataTransUtil.returnData(0,"用户名不存在"); }catch (IncorrectCredentialsException e) { return DataTransUtil.returnData(0, "密码错误"); }catch (LockedAccountException e){ return DataTransUtil.returnData(0,"用户已被锁定,无法登录"); }catch (Exception e){ return DataTransUtil.returnData(0,"其他错误"); } return DataTransUtil.returnData(); } @Override public User findByName(String username) { return userRepository.findByName(username); } @Override public User getLoginUser() { return (User)SecurityUtils.getSubject().getPrincipal(); } @Override public List<Role> findRolesByUid(Long id) { List<UserRole> userRoleList = userRoleRepository.findRolesByUid(id); List<Role> roleList = new ArrayList<>(); for(UserRole userRole : userRoleList){ roleList.add(userRole.getRole()); } return roleList; } @Override public List<Permission> findPermissionsByUid(Long id) { List<UserRole> userRoleList = userRoleRepository.findRolesByUid(id); List<Long> roleIds = new ArrayList<>(); for(UserRole userRole : userRoleList){ roleIds.add(userRole.getRole().getId()); } List<RolePermission> rolePermissionList = rolePermissionRepository.findPermissionsByUid(roleIds); List<Permission> permissionList = new ArrayList<>(); for(RolePermission rolePermission : rolePermissionList){ if(!permissionList.contains(rolePermission.getPermission())){ permissionList.add(rolePermission.getPermission()); } } return permissionList; }}
Dao层(详细代码不贴了,自己定义就行):
工具类:
package com.example.demo.utils;import org.springframework.util.StringUtils;import java.util.HashMap;/** * Created by lean on 2017/9/18. */public class DataTransUtil { private static Integer defaultCode = 1; private static String defaultMessage = "succesful"; public static HashMap<String,Object> returnData(Integer code,String message,Object data){ HashMap<String,Object> map = new HashMap<>(); if(null != code){ map.put("code",code); }else{ map.put("code",defaultCode); } if(!StringUtils.isEmpty(message)){ map.put("message",message); }else{ map.put("message",defaultMessage); } map.put("data",data); return map; } public static HashMap<String,Object> returnData(Object data){ return returnData(null,null,data); } public static HashMap<String,Object> returnData(){ return returnData(null,null,null); } public static HashMap<String,Object> returnData(Integer code,String message){ return returnData(code,message,null); }}
从 getLoginUser 接口方法获得登录用户信息展示:
附加-密码加密方法:
package com.example.demo;import org.apache.shiro.crypto.hash.Md5Hash;import org.apache.shiro.crypto.hash.SimpleHash;import org.apache.shiro.util.ByteSource;/** * Created by John.Zhang on 2017/10/11. */public class Test { public static void main(String[] args) { String newPassword = new SimpleHash( "MD5", //加密算法 "123", //密码 ByteSource.Util.bytes("10086"), //salt盐 username + salt 2 //迭代次数 ).toHex(); System.out.print(newPassword); }}
阅读全文
0 0
- SpringBoot学习-简单shiro权限控制
- SpringBoot+shiro整合学习之登录认证和权限控制
- SpringBoot+shiro整合学习之登录认证和权限控制
- springboot集成shiro 实现权限控制
- springboot+shiro+mybatis实现角色权限控制
- springboot shiro权限控制讲解01 每天进步百分之一
- Shiro简单的角色权限控制
- springboot中shiro控制
- 使用shiro实现权限控制学习总结
- springboot学习之后台权限控制
- shiro、SpringMVC权限控制
- shiro、SpringMVC权限控制
- shiro权限控制
- 权限控制框架 shiro
- Shiro 权限控制框架
- Apache Shiro 权限控制
- shiro权限控制
- Shiro 权限控制
- Java多线程编程-(7)-使用ReentrantReadWriteLock实现Lock并发
- jsr303表单校验配置。
- centos 7 下 安装Jupyter notebook的步骤
- Sublime 首选项方法
- TCP面试相关总结
- SpringBoot学习-简单shiro权限控制
- 苏宁总结
- APFS 苹果文件格式的小介绍 Apple File System
- JS验证银行卡号有效性
- 创建学生成绩双链表
- Centos命令
- 机器学习实战---详解模型评价指标
- 异步赠书:10月Python畅销书升级
- mCustomScrollbar插件的theme参数