网上有很多整合shiro的博客分享,但是貌似没找到一个完整,并且能够实现的。不是包的问题,就是代码的问题,也可能是自己的问题,或者版本的问题。所以,整理了一版自己已应用的.
maven依赖:
org.springframework.boot
spring-boot-starter-parent
2.0.2.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.RELEASE
pom
import
org.springframework.cloud
spring-cloud-starter-config
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
net.sourceforge.nekohtml
nekohtml
1.9.22
org.apache.shiro
shiro-spring
1.4.0
mysql
mysql-connector-java
5.1.35
com.alibaba
druid
1.0.11
org.projectlombok
lombok
true
com.alibaba
fastjson
1.2.47
commons-io
commons-io
2.4
org.apache.tomcat.embed
tomcat-embed-jasper
provided
javax.servlet
javax.servlet-api
provided
javax.servlet
jstl
MyShiroRealm.java(权限配置)
import com.simple.users.dto.entity.UserInfo; import com.simple.users.service.UserInfoService; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import javax.annotation.Resource; import java.util.HashSet; import java.util.Set; public class MyShiroRealm extends AuthorizingRealm { @Resource private UserInfoService userInfoService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); UserInfo userInfo = (UserInfo) principals.getPrimaryPrincipal(); /* * for (SysRole role : userInfo.getRoleList()) { * authorizationInfo.addRole(role.getRole()); for (SysPermission p : * role.getPermissions()) { * authorizationInfo.addStringPermission(p.getPermission()); } } */ // 获取用户角色 Set
roleSet = new HashSet
(); roleSet.add(""); info.setRoles(roleSet); // 获取用户权限 Set
permissionSet = new HashSet
(); permissionSet.add("权限添加"); permissionSet.add("权限删除"); info.setStringPermissions(permissionSet); return info; } / * 主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。 * * @param authcToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; String username = token.getUsername(); UserInfo userInfo = userInfoService.findByUsername(username); if (userInfo == null) { return null; } String password = new String((char[]) token.getCredentials()); String pwdMd5 = (new Md5Hash(password, username)).toHex(); System.out.println("----->>pwdMd5====" + pwdMd5); UserInfo user = new UserInfo(); user.setUsername(username); user.setPassword(pwdMd5); return new SimpleAuthenticationInfo(user, pwdMd5, ByteSource.Util.bytes(username), getName()); } }
ShiroConfig.java(shiro配置)
import com.simple.utils.Base64Util; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; 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.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; @Configuration public class ShiroConfig { / * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean * 开启thymeleaf模板访问,注释则使用配置的jsp或者HTML访问模式 * @return */ // @Bean // public ShiroDialect shiroDialect() { // return new ShiroDialect(); // } @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { System.out.println("--------ShiroConfiguration.shirFilter()"); // 添加安全管理器 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不设置默认会自动寻找Web工程根目录下的"/index.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/"); // 登录成功后要跳转的链接 // shiroFilterFactoryBean.setSuccessUrl("/?path=user/main"); // 添加shiro内置过滤器 / * anon:表示可以匿名使用。 authc:表示需要认证(登录)才能使用,没有参数 * * roles:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时, * 例如admins/user/=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。 * * perms:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割, * 例如/admins/user/=perms["user:add:*,user:modify:*"], * 当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。 * * rest:根据请求的方法,相当于/admins/user/=perms[user:method] * ,其中method为post,get,delete等。 * * port:当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString, * 其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口, * queryString是你访问的url里的?后面的参数。 authcBasic:没有参数表示httpBasic认证 * * ssl:表示安全的url请求,协议为https user:当登入操作时不做检查 */ Map
filterChainDefinitionMap = new LinkedHashMap
(); // 静态资源的处理 filterChainDefinitionMap.put("/js/", "anon"); filterChainDefinitionMap.put("/css/", "anon"); filterChainDefinitionMap.put("/img/", "anon"); filterChainDefinitionMap.put("/fonts/", "anon"); filterChainDefinitionMap.put("/plugins/", "anon"); // // 请求路径的处理 filterChainDefinitionMap.put("/H-PLE/", "authc"); // 退出系统的过滤器 filterChainDefinitionMap.put("/userInfo/logout", "logout"); filterChainDefinitionMap.put("/userInfo/login", "anon"); // 默认所有资源必须认证才能访问 filterChainDefinitionMap.put("/", "authc"); // 未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } / * 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 ) * * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(1);// 散列的次数(默认一次),比如散列两次,相当于 md5(md5("")); return hashedCredentialsMatcher; } @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); // 注入记住我管理器; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } / * cookie对象; * * @return */ public SimpleCookie rememberMeCookie() { // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //
simpleCookie.setMaxAge(); return simpleCookie; } / * cookie管理对象;记住我功能 * * @return */ public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); // rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) try { cookieRememberMeManager.setCipherKey(Base64Util.decode("3AvVhmFLUs0KTA3Kprsdag==")); } catch (Exception e) { e.printStackTrace(); } return cookieRememberMeManager; } / * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean(name = "simpleMappingExceptionResolver") public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("DatabaseException", "databaseError");// 数据库异常处理 mappings.setProperty("UnauthorizedException", "403"); r.setExceptionMappings(mappings); // None by default r.setDefaultErrorView("error"); // No default r.setExceptionAttribute("ex"); // Default is "exception" // r.setWarnLogCategory("example.MvcLogger"); // No default return r; } }
UserController.java(登录应用)
@ResponseBody @RequestMapping(value = "/login", method = RequestMethod.POST, produces = { "application/json; charset=UTF-8" }) public Object login(@RequestBody JSONObject jsonP) { JSONObject result = new JSONObject(); JSONObject resultHd = new JSONObject(); JSONObject resultBd = new JSONObject(); String userName = Null.nullToSpace(jsonP.getString("userName")); String passWord = Null.nullToSpace(jsonP.getString("passWord")); Boolean rememberMe = jsonP.getBoolean("agree"); System.out.println("userName--" + userName + "; passWord--" + passWord + "; rememberMe--" + rememberMe); UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord, rememberMe); try { SecurityUtils.getSubject().login(token); resultHd.put("error", "成功"); resultHd.put("errorCode", "0"); resultHd.put("data", new HashMap()); } catch (UnknownAccountException e) { resultHd.put("error", "失败"); resultHd.put("errorCode", "2"); resultHd.put("data", new HashMap()); e.printStackTrace(); } catch (IncorrectCredentialsException e) { resultHd.put("error", "失败"); resultHd.put("errorCode", "3"); resultHd.put("data", new HashMap()); e.printStackTrace(); } catch (AuthenticationException e) { // 其他错误,比如锁定,如果想单独处理请单独catch处理 resultHd.put("error", "失败"); resultHd.put("errorCode", "1"); resultHd.put("data", new HashMap()); e.printStackTrace(); } result.put("header", resultHd); result.put("body", resultBd); return result; }
User实体:
权限类:SysPermission.java import lombok.Getter; import lombok.Setter; import lombok.ToString; import javax.persistence.*; import java.io.Serializable; import java.util.List; @Getter @Setter @ToString @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
roles; } ---------------------------------------------------------------------------------------- 角色类:SysRole.java import lombok.Getter; import lombok.Setter; import lombok.ToString; import javax.persistence.*; import java.util.List; @Getter @Setter @ToString @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
permissions; // 用户 - 角色关系定义; @ManyToMany @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "roleId") }, inverseJoinColumns = { @JoinColumn(name = "uid") }) private List
userInfos;// 一个角色对应多个用户 // 省略 get set 方法 } ---------------------------------------------------------------------------------------- 用户类:UserInfo.java import lombok.Getter; import lombok.Setter; import lombok.ToString; import javax.persistence.*; import java.io.Serializable; import java.util.List; @Getter @Setter @ToString @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
roleList;// 一个用户具有多个角色 / * 密码盐. * * @return */ public String getCredentialsSalt() { return this.username + this.salt; } // 重新对盐重新进行了定义,用户名+salt,这样就更加不容易被激活成功教程 }
数据:
用户表:账号admin 密码admin INSERT INTO `user_info`(`uid`, `name`, `password`, `salt`, `state`, `username`) VALUES (1, '管理员', 'f6fdffe48c908deb0f4c3bd36c032e72', '87', 0, 'admin'); 权限表: INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (1, b'0', '用户管理', 0, '0/', 'userInfo:view', 'menu', 'userInfo/userList'); INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (2, b'0', '用户添加', 1, '0/1', 'userInfo:add', 'button', 'userInfo/userAdd'); INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (3, b'0', '用户删除', 1, '0/1', 'userInfo:del', 'button', 'userInfo/userDel'); 角色表: INSERT INTO `sys_role`(`id`, `available`, `description`, `role`) VALUES (1, b'0', '管理员', 'admin'); INSERT INTO `sys_role`(`id`, `available`, `description`, `role`) VALUES (2, b'0', 'VIP会员', 'vip');
里面的Null类引用,可以在 https://blog.csdn.net/weixin_/article/details/ (Java 一些常用工具类)这里面找工具类。

yml配置:
druid: stat: mergeSql: true; slowSqlMillis: 5000 logging: level: com: DEBUG mybatis: mapper-locations: classpath:com/simple/*/dto/maps/*Mapper.xml type-aliases-package: com.simple.* server: port: 8081 servlet: context-path: / spring: datasource: driverClassName: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/oa?characterEncoding=utf8&autoReconnect=true&useSSL=false&useAffectedRows=true username: root password: root filters: stat,wall,log4j initialSize: 5 maxActive: 20 maxPoolPreparedStatementPerConnectionSize: 20 maxWait: 60000 minEvictableIdleTimeMillis: minIdle: 5 poolPreparedStatements: true testOnBorrow: false testOnReturn: false testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL http: encoding: charset: UTF-8 enabled: true jpa: show-sql: true hibernate: ddl-auto: update naming: physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy properties: hibernate: dialect: org.hibernate.dialect.MySQL5Dialect mvc: locale: zh_CN view: prefix: /WEB-INF/jsp/ suffix: .jsp static-path-pattern: / #资源名称md5方式 resources: chain: strategy: content: enabled: true paths: /
以上就是shiro完整代码,如有疑问,随时评论.
转载请注明出处!
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/204228.html原文链接:https://javaforall.net
