软件152 尹以操

  springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题。仅以此篇记录我对shiro的学习,如有对过客造成不便,实在抱歉!

  一、加入jar包

  既然要用到shiro,当然要加入它的jar包咯,在pom.xml中jar包依赖中加入:

  1. <dependency>
  2. <groupId>org.apache.shiro</groupId>
  3. <artifactId>shiro-spring</artifactId>
  4. <version>1.2.2</version>
  5. </dependency>

  二、写实体类

  这需要三个实体类,hibernate自动生成5个表

  User实体(用户):

  1. package com.cy.coo.bean;
  2.  
  3. import java.util.List;
  4. import javax.persistence.Column;
  5. import javax.persistence.Entity;
  6. import javax.persistence.FetchType;
  7. import javax.persistence.GeneratedValue;
  8. import javax.persistence.Id;
  9. import javax.persistence.JoinColumn;
  10. import javax.persistence.JoinTable;
  11. import javax.persistence.ManyToMany;
  12.  
  13. import com.fasterxml.jackson.annotation.JsonBackReference;
  14.  
  15. @Entity
  16. public class User {
  17.  
  18. @Id
  19. @GeneratedValue
  20. private Integer user_id;//用户序号
  21.  
  22. @Column(unique=true)
  23. private String name;//账户
  24.  
  25. private String password;//密码
  26.  
  27. private String salt;//盐
  28.  
  29. private Integer state;//用户状态
  30.  
  31. private String createtime;//创建时间
  32.  
  33. @ManyToMany(fetch=FetchType.EAGER)//立即从数据库中进行加载数据;
  34. @JoinTable(name="User_Role",joinColumns={@JoinColumn(name="user_id")},
  35. inverseJoinColumns={@JoinColumn(name="role_id")})
  36. private List<Role> roleList;
  37.  
  38. @JsonBackReference
  39. public List<Role> getRoleList(){
  40. return roleList;
  41. }
  42.  
  43. public void setRoleList(List<Role> roleList){
  44. this.roleList=roleList;
  45. }
  46.  
  47. 注:其它gettersetter省略
  48.  
  49. }

  关于为什么要在getRolelist这个方法上加上@JsonBackReference注解,可以查看这篇文章http://blog.csdn.net/maxu12345/article/details/45538157

  Role实体(角色):

  1. package com.cy.coo.bean;
  2.  
  3. import java.io.Serializable;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6.  
  7. import javax.persistence.Entity;
  8. import javax.persistence.FetchType;
  9. import javax.persistence.GeneratedValue;
  10. import javax.persistence.Id;
  11. import javax.persistence.JoinColumn;
  12. import javax.persistence.JoinTable;
  13. import javax.persistence.ManyToMany;
  14.  
  15. import com.fasterxml.jackson.annotation.JsonBackReference;
  16.  
  17. @Entity
  18. public class Role implements Serializable {
  19. private static final long serialVersionUID = 1L;
  20.  
  21. @Id
  22. @GeneratedValue
  23. private Integer role_id;//角色序号
  24.  
  25. private String role_name;//角色名称
  26.  
  27. private String role_description;//角色描述
  28.  
  29. @ManyToMany
  30. @JoinTable(name = "User_Role", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = {
  31. @JoinColumn(name = "user_id") })
  32. private List<User> userList=new ArrayList<>();
  33.  
  34. @ManyToMany(fetch=FetchType.EAGER)
  35. @JoinTable(name="Role_Function",joinColumns={@JoinColumn(name="role_id")},inverseJoinColumns={
  36. @JoinColumn(name="function_id")})
  37. private List<Function> functionList=new ArrayList<>();
  38.  
  39. @JsonBackReference
  40. public List<Function> getFunctionList(){
  41. return functionList;
  42. }
  43.  
  44. public void setFunctionList(List<Function> functionList){
  45. this.functionList=functionList;
  46. }
  47.  
  48. @JsonBackReference
  49. public List<User> getUserList() {
  50. return userList;
  51. }
  52.  
  53. public void setUserList(List<User> userList) {
  54. this.userList = userList;
  55. }
  56.  
  57. public Integer getRole_id() {
  58. return role_id;
  59. }
  60.  
  61. public void setRole_id(Integer role_id) {
  62. this.role_id = role_id;
  63. }
  64.  
  65. public String getRole_name() {
  66. return role_name;
  67. }
  68.  
  69. public void setRole_name(String role_name) {
  70. this.role_name = role_name;
  71. }
  72.  
  73. public String getRole_description() {
  74. return role_description;
  75. }
  76.  
  77. public void setRole_description(String role_description) {
  78. this.role_description = role_description;
  79. }
  80.  
  81. }

  Function实体(权限):

  1. package com.cy.coo.bean;
  2.  
  3. import java.util.List;
  4.  
  5. import javax.persistence.Entity;
  6. import javax.persistence.GeneratedValue;
  7. import javax.persistence.Id;
  8. import javax.persistence.JoinColumn;
  9. import javax.persistence.JoinTable;
  10. import javax.persistence.ManyToMany;
  11.  
  12. @Entity
  13. public class Function {
  14.  
  15. @Id
  16. @GeneratedValue
  17. private Integer function_id;//功能序号
  18.  
  19. private String permission;//权限字符串
  20.  
  21. @ManyToMany
  22. @JoinTable(name = "Role_Function", joinColumns = { @JoinColumn(name = "function_id") }, inverseJoinColumns = {
  23. @JoinColumn(name = "role_id") })
  24. private List<Role> roleList;
  25.  
  26. public List<Role> getRoleList() {
  27. return roleList;
  28. }
  29.  
  30. public void setRoleList(List<Role> roleList) {
  31. this.roleList = roleList;
  32. }
  33.  
  34. public Integer getFunction_id() {
  35. return function_id;
  36. }
  37.  
  38. public void setFunction_id(Integer function_id) {
  39. this.function_id = function_id;
  40. }
  41.  
  42. public String getPermission() {
  43. return permission;
  44. }
  45.  
  46. public void setPermission(String permission) {
  47. this.permission = permission;
  48. }
  49.  
  50. }

  这几个实体类的具体关系如下图,也完美的解释了为什么会生成5张表:

  三、写一个与前端交互的controller方法,service层的具体逻辑的方法

  1. @PostMapping(value = "/logon")
  2. public Object logon(@RequestBody Login user) {
  3.  
  4. return userService.login(user);
  5. }

  这个方法就是将前端传来的username和password封装到Login类中,Login类也只有这两个属性,然后调用Service层的login方法来处理。下面是service的login方法:

  1. /**
  2. * 用户登录 create by yyc 2017年5月12日下午4:31:26
  3. */
  4. @Override
  5. public Object login(Login user) {
  6. String username = user.getUsername().trim();
  7. String password = user.getPassword().trim();
  8.  
  9. // 检查空值
  10. if (!CheckObjectField.CheckField(user)) {
  11. throw new ResultException(CheckObjectField.FieldName + "为空!");
  12. }
  13.  
  14. // 检查用户状态
  15. Integer userState = userRepository.findUserState(username);
  16. if (new Integer("1").equals(userState)) {
  17. throw new ResultException("该用户已锁定");
  18. }
  19.  
  20. // 1、获取Subject实例对象
  21. Subject currentUser = SecurityUtils.getSubject();
  22.  
  23. // 2、判断当前用户是否登录
  24. if (currentUser.isAuthenticated() == false) {
  25. // 3、将用户名和密码封装到UsernamePasswordToken
  26. UsernamePasswordToken token = new UsernamePasswordToken(username, password);
  27.  
  28. // 4、认证
  29. try {
  30. currentUser.login(token);// 传到MyAuthorizingRealm类中的方法进行认证
  31. Session session = currentUser.getSession();
  32. session.setAttribute("username", username);
  33. } catch (AuthenticationException e) {
  34. throw new ResultException("密码或用户名错误");
  35. }
  36. }
  37. // 根据用户名查询角色信息
  38. List<String> RoleNames = roleService.findRoleName(username);
  39.  
  40. return new LoginReturn(username, RoleNames);
  41.  
  42. }

  service中主要是将用户名和密码封装到shiro的UsernamePasswordToken中,然后将token对象放到SecurityUtils.getSubject()的login方法中,以便shiro认证登录使用。认证失败就会抛出AuthenticationException这个异常,就对异常进行相应的操作,这里的处理是抛出一个自定义异常ResultException。

  四、写我认为的shiro的核心类

  1. package com.cy.coo.shiro;
  2.  
  3. import org.apache.shiro.authc.AuthenticationException;
  4. import org.apache.shiro.authc.AuthenticationInfo;
  5. import org.apache.shiro.authc.AuthenticationToken;
  6. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  7. import org.apache.shiro.authc.UsernamePasswordToken;
  8. import org.apache.shiro.authz.AuthorizationInfo;
  9. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  10. import org.apache.shiro.realm.AuthorizingRealm;
  11. import org.apache.shiro.subject.PrincipalCollection;
  12. import org.apache.shiro.util.ByteSource;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16.  
  17. import com.cy.coo.bean.Function;
  18. import com.cy.coo.bean.Role;
  19. import com.cy.coo.bean.User;
  20. import com.cy.coo.service.UserService;
  21.  
  22. /**
  23. *
  24. *
  25. * @author E-mail:34782655@qq.com
  26. * @version 创建时间:2017年5月8日 上午10:50:50
  27. * 类说明:
  28. * --
  29. */
  30. public class MyAuthorizingRealm extends AuthorizingRealm {
  31.  
  32. private final static Logger logger=LoggerFactory.getLogger(MyAuthorizingRealm.class);
  33.  
  34. @Autowired
  35. private UserService userService;
  36. //shiro的权限配置方法
  37. @Override
  38. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  39.  
  40. logger.info("权限配置-->doGetAuthorizationInfo");
  41.  
  42. SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  43. logger.info("----------------------------->"+principals.getPrimaryPrincipal());
  44. User user=(User) principals.getPrimaryPrincipal();
  45. for(Role role:user.getRoleList()){
  46. authorizationInfo.addRole(role.getRole_name());
  47. for(Function function:role.getFunctionList()){
  48. authorizationInfo.addStringPermission(function.getPermission());
  49. }
  50. }
  51.  
  52. logger.info("用户"+user.getName()+"具有的角色:"+authorizationInfo.getRoles());
  53. logger.info("用户"+user.getName()+"具有的权限:"+authorizationInfo.getStringPermissions());
  54.  
  55. return authorizationInfo;
  56. }
  57.  
  58. //shiro的身份验证方法
  59. @Override
  60. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  61.  
  62. logger.info("正在验证身份...");
  63. SimpleAuthenticationInfo info=null;
  64.  
  65. //将token转换成UsernamePasswordToken
  66. UsernamePasswordToken upToken = (UsernamePasswordToken) token;
  67. //从转换后的token中获取用户名
  68. String username= upToken.getUsername();
  69. logger.info("----->"+username);
  70.  
  71. //查询数据库,得到用户
  72. User user=userService.findByName(username);
  73. if(user==null){
  74. return null;
  75. }
  76.  
  77. //得到加密密码的盐值
  78. ByteSource salt = ByteSource.Util.bytes(user.getSalt());
  79. // logger.info("加密密码的盐:"+salt);
  80. // //得到盐值加密后的密码:只用于方便数据库测试,后期不会用到。
  81. // Object md = new SimpleHash("MD5",upToken.getPassword(),salt,1024);
  82. // logger.info("盐值加密后的密码:"+md);
  83.  
  84. info = new SimpleAuthenticationInfo(
  85. user, //用户名
  86. user.getPassword(), //密码
  87. salt, //加密的盐值
  88. getName() //realm name
  89. );
  90. return info;
  91. }
  92.  
  93. }

  这个类继承shiro的AuthorizingRealm ,主要有两个方法,一个是权限配置,一个是身份认证,权限配置:当我们要用到权限时shiro会回调doGetAuthorizationInfo这个方法,对当前的用户分配权限,这个方法中的嵌套for循环是怎么回事呢,其实就是将数据库中的对应角色、权限放进shiro中,让他来管理,这需要实体类User中有getRoleList()、getRole_name()和getFunctionList()、getPermission这几个方法,这几个个方法就是设计数据库和实体类时的东西了,关于shiro权限相关的实体类在前面已经给出了。身份认证:在用户登录认证的时候回调,认证失败就抛出AuthenticationException。

  五、shiro配置类

  1. package com.cy.coo.shiro;
  2.  
  3. import java.util.LinkedHashMap;
  4. import java.util.Map;
  5.  
  6. import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
  7. import org.apache.shiro.cache.ehcache.EhCacheManager;
  8. import org.apache.shiro.mgt.SecurityManager;
  9. import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
  10. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  11. import org.apache.shiro.web.mgt.CookieRememberMeManager;
  12. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  13. import org.apache.shiro.web.servlet.SimpleCookie;
  14. import org.slf4j.Logger;
  15. import org.slf4j.LoggerFactory;
  16. import org.springframework.beans.factory.annotation.Qualifier;
  17. import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
  18. import org.springframework.context.annotation.Bean;
  19. import org.springframework.context.annotation.Configuration;
  20. import org.springframework.core.io.ClassPathResource;
  21.  
  22. @Configuration // 等价于beans
  23. public class ShiroConfig {
  24.  
  25. private static final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);
  26.  
  27. @Bean(name = "securityManager")
  28. public SecurityManager securityManager(@Qualifier("authRealm") MyAuthorizingRealm authRealm,
  29. @Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager) {
  30. log.info("securityManager()");
  31. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  32. // 设置realm.
  33. securityManager.setRealm(authRealm);
  34.  
  35. // 设置rememberMe管理器
  36. securityManager.setRememberMeManager(cookieRememberMeManager);
  37.  
  38. return securityManager;
  39. }
  40.  
  41. /**
  42. * realm
  43. *
  44. * @return
  45. */
  46. @Bean(name = "authRealm")
  47. public MyAuthorizingRealm myAuthRealm(
  48. @Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher,
  49. @Qualifier("ehCacheManager") EhCacheManager ehCacheManager) {
  50. log.info("myShiroRealm()");
  51. MyAuthorizingRealm myAuthorizingRealm = new MyAuthorizingRealm();
  52. // 设置密码凭证匹配器
  53. myAuthorizingRealm.setCredentialsMatcher(matcher); // myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
  54. // 设置缓存管理器
  55. myAuthorizingRealm.setCacheManager(ehCacheManager);
  56.  
  57. return myAuthorizingRealm;
  58. }
  59.  
  60.     /**
  61. * 缓存管理器
  62. * @return
  63. */
  64. @Bean(value="ehCacheManager")
  65. public EhCacheManager ehCacheManager(@Qualifier("ehCacheManagerFactoryBean") EhCacheManagerFactoryBean bean) {
  66. log.info("ehCacheManager()");
  67. EhCacheManager cacheManager = new EhCacheManager();
  68. cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
  69. return cacheManager;
  70. }
  71.  
  72. /**
  73. * cookie对象;
  74. *
  75. * @return
  76. */
  77. @Bean
  78. public SimpleCookie rememberMeCookie() {
  79. log.info("rememberMeCookie()");
  80. // 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe
  81. SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
  82. // <!-- 记住我cookie生效时间30天(259200) ,单位秒;-->
  83. simpleCookie.setMaxAge(259200);
  84. return simpleCookie;
  85. }
  86.  
  87. /**
  88. * 记住我管理器 cookie管理对象;
  89. *
  90. * @return
  91. */
  92. @Bean(name = "cookieRememberMeManager")
  93. public CookieRememberMeManager rememberMeManager() {
  94. System.out.println("rememberMeManager()");
  95. CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
  96. cookieRememberMeManager.setCookie(rememberMeCookie());
  97. return cookieRememberMeManager;
  98. }
  99.  
  100. /**
  101. * 密码匹配凭证管理器
  102. *
  103. * @return
  104. */
  105. @Bean(name = "hashedCredentialsMatcher")
  106. public HashedCredentialsMatcher hashedCredentialsMatcher() {
  107. log.info("hashedCredentialsMatcher()");
  108. HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
  109.  
  110. hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 散列算法:这里使用MD5算法;
  111. hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于
  112. // md5(md5(""));
  113.  
  114. return hashedCredentialsMatcher;
  115. }
  116.  
  117. /**
  118. * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; Controller才能使用@RequiresPermissions
  119. *
  120. * @param securityManager
  121. * @return
  122. */
  123. @Bean
  124. public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
  125. @Qualifier("securityManager") SecurityManager securityManager) {
  126. log.info("authorizationAttributeSourceAdvisor()");
  127. AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
  128. authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
  129. return authorizationAttributeSourceAdvisor;
  130. }
  131.  
  132. @Bean
  133. public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
  134. log.info("shirFilter()");
  135. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  136.  
  137. // 必须设置 SecurityManager
  138. shiroFilterFactoryBean.setSecurityManager(securityManager);
  139.  
  140. // 拦截器.
  141. Map<String, String> map = new LinkedHashMap<String, String>();
  142.  
  143. map.put("/logout", "logout");
  144. map.put("/login", "anon");
  145. map.put("/logon", "anon");
  146.  
  147. map.put("/**", "authc");
  148.  
  149. // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
  150. shiroFilterFactoryBean.setLoginUrl("/login");
  151. // 登录成功后要跳转的链接
  152. shiroFilterFactoryBean.setSuccessUrl("/index");
  153. // 未授权界面;
  154. shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
  155.  
  156. shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
  157. return shiroFilterFactoryBean;
  158. }
  159. }

  这个没什么好说的,最后一个类是shiro的过滤器配置。可以看到我在每个方法上面加了一个@Bean(name="..."),其实这是spring的注解,将这个类放到spring容器中管理,在方法形参中使用@Qualifier(...)来使用它,以致于我们在方法体中调用某个方法时就方面多了。

在这里,关于shiro在springboot中的基础配置就完成了。下面是期间遇到的错误解决方案:

错误一:关于实体类的错误,springboot 中hibernate懒加载  报错....................................No  Session
解决方法:新建类 配置OpenEntityManagerInViewFilter    以及  上面角色类(表)和用户类(表)(Role、User)Role的红色字体也是必须的,及@ManyToMany(fetch=FetchType.EAGER)
由于博主基础的局限还不知道具体的原因是什么,但是解决了就好。
  1. @Configuration
  2. public class HibernateConfig {
  3. @Bean
  4. public FilterRegistrationBean registerOpenEntityManagerInViewFilterBean() {
  5. FilterRegistrationBean registrationBean = new FilterRegistrationBean();
  6. OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter();
  7. registrationBean.setFilter(filter);
  8. registrationBean.setOrder(5);
  9. return registrationBean;
  10. }
  11. }

参考文章:

http://stackoverflow.com/questions/33622222/spring-boot-opensessioninviewfilter-with-actuator-and-custom-security 

http://www.jianshu.com/p/a827ecdda99f

http://www.w_2bc.com/article/201653 /*这个链接博客园不让我发啊,把w_2_b_c中的下划线删了即可*/

错误二:这个在前面也提到过了,返回json数据出现Could not write JSON document: Infinite recursion(无法编写JSON文档:无限递归 );

在后面的使用中发现这个错误也是这样解决的,java.lang.IllegalStateException: Cannot call sendError() after the response has been committed,错误页面到最后就是这样,如图:

解决方法:

  在controller返回数据到统一json转换的时候,出现了json infinite recursion stackoverflowerror的错误,即json在将对象转换为json格式的数据的时候,出现了无限递归调用的情况。
具体的情况如下:
    A类中,有个属性:List<B> b, A与B的关系为 OneToMany;在B类中,有属性A a,引用到A中的字段id,并作为外键。hibernate查询结果正常,可以看到返回的A对象中,有b参数值,但在json转换的时候就出现了无限递归的情况。个人分析,应该是json在序列化A中的b属性的时候,找到了B类,然后序列化B类,而B类中有a属性,因此,为了序列化a属性,json又得去序列化A类,如此递归反复,造成该问题。
解决:
    在B类中a的getter setter方法上加注解@JsonBackReference,其实自己试过只在getter方法上加@JsonBackReference也够了。
 
 

Springboot+shiro配置笔记+错误小结的更多相关文章

  1. (转)Springboot+shiro配置笔记+错误小结

    springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题.仅以此篇记录我对shiro的学习,如有对过客造成不便,实在抱 ...

  2. Springboot+shiro配置笔记+错误小结(转)

    软件152 尹以操 springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题.仅以此篇记录我对shiro的学习,如有对 ...

  3. springboot shiro配置

    导入相关包(这里配合使用Ehcache缓存) <dependency> <groupId>org.apache.shiro</groupId> <artifa ...

  4. SpringBoot整合Shiro 二:Shiro配置类

    环境搭建见上篇:SpringBoot整合Shiro 一:搭建环境 Shiro配置类配置 shiro的配置主要集中在 ShiroFilterFactoryBean 中 关于权限: anon:无需认证就可 ...

  5. springboot学习笔记:11.springboot+shiro+mysql+mybatis(通用mapper)+freemarker+ztree+layui实现通用的java后台管理系统(权限管理+用户管理+菜单管理)

    一.前言 经过前10篇文章,我们已经可以快速搭建一个springboot的web项目: 今天,我们在上一节基础上继续集成shiro框架,实现一个可以通用的后台管理系统:包括用户管理,角色管理,菜单管理 ...

  6. SpringBoot+Shiro学习(七):Filter过滤器管理

    SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注  0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...

  7. Shiro学习笔记(5)——web集成

    Web集成 shiro配置文件shiroini 界面 webxml最关键 Servlet 測试 基于 Basic 的拦截器身份验证 Web集成 大多数情况.web项目都会集成spring.shiro在 ...

  8. springboot+shiro

    作者:纯洁的微笑 出处:http://www.ityouknow.com/ 这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公 ...

  9. Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...

随机推荐

  1. android monkey app乱点测试

    Monkey是Android中的一个命令行工具 查看包名:查看电脑中某一位置的apk文件的包名:PC打开CMD-进入TMG目录-运行设备--查看包名aapt dump badging *.apk(ap ...

  2. 在后台运行Python脚本服务

    在服务器,程序都是后台运行的,当写的python脚本时,需要:   你要是想python robot.py & 是不行的,一旦用户登出,脚本就自动退出了.用at, cron也可以实现不过我发现 ...

  3. 01 awk工具的使用

    一:登录mysql后查看mysql的连接状态:show status ; 回车 如图所示: |Threads_connected    | 1| Threads_running       | 1   ...

  4. 第二百七十三节,Tornado框架-文件上传

    Tornado框架-文件上传 第一.普通表单上传文件 self.request.files["fafafa"] 获取上传文件信息,参数["上传文件框的name名称&quo ...

  5. 【NOIP模拟题】Permutation(dp+高精度)

    首先我们可以这样想: 设状态f[i, j]表示1-i序列有j个'<'的方案数 那么考虑转移 因为i比i-1大,所以可以考虑从i-1来转移.首先i是要插入1-i-1这个序列的,所以我们可以思考插入 ...

  6. npoi导出excel_asp.net MVC

    下载路径: http://files.cnblogs.com/files/gaocong/npoi_for_mysql_mvc.rar

  7. mathtype免费版下载及序列号获取地址

    在编辑公式这个方面来说,MathType是使用最多的一个工具,因为它操作简单,不需要复杂的学习过程就可以很快地掌握操作技巧,并且功能也比Office自带的公式编辑器完善很多,可以对公式进行批量修改.编 ...

  8. 【代码备份】pocs.m

    超分辨率算法代码 POCS算法,凸集投影法. pocs.m,没有调用的代码,没看懂..只有这个函数..抱歉. function y = pocs(s,delta_est,factor) % POCS ...

  9. iOS 关于 UIKit 专栏应该写在最前面的话

    iOS 关于 UIKit 应该写在最前面的话 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...

  10. thinkphp5如何使用layout

    thinkphp5的layout和以前的版本有点差异. 首先开启配置文件中的 'template' => [      'layout_on' => true,      // 'layo ...