springboot学习心得3

整合springboot shiro 

目录结构

在引入web,mysql,mybatis 的项目基础上引入shiro,thymeleaf

增加yml文件(配置信息) 

  1. #默认使用配置
  2. spring:
  3. profiles:
  4. active: dev
  5.  
  6. #公共配置与profiles选择无关
  7. mybatis:
  8. typeAliasesPackage: com.springboot.shiro.model
  9. mapperLocations: classpath:mapper/*.xml
  10. #sql 日志
  11. logging:
  12. level:
  13. com.springboot.shiro.dao: trace
  14. ---
  15. #开发配置
  16. spring:
  17. profiles: dev
  18. datasource:
  19. url: jdbc:mysql://localhost:3306/qidi_shiro
  20. username: root
  21. password: geyanxin
  22. driver-class-name: com.mysql.jdbc.Driver
  23.  

 

创建自定义MyShiroRealm 

 print ?
  1. package com.springboot.shiro.config;


    import javax.annotation.Resource;


    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 com.springboot.shiro.model.User;
    import com.springboot.shiro.service.UserService;


    public class MyShiroRealm extends AuthorizingRealm{
    @Resource
    private UserService userService;
    /**
     * 权限设置
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String userName=(String)principals.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            authorizationInfo.setRoles(userService.getRoles(userName));
    return authorizationInfo;
    }
    /**
     * 身份认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            //获取用户的输入的账号.
            String userName = (String)token.getPrincipal();
            //通过username从数据库中查找 User对象,如果找到,没找到.
            User user = userService.getByUserName(userName);
            if(user == null){
                return null;
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
             user.getName(), //用户名
             user.getUserPassword(), //密码
                    getName()  //realm name
            );
            return authenticationInfo;
    }


    }

创建shiroConfig

 
  1. package com.springboot.shiro.config;


    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    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 {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    //拦截器.
    Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
    // 配置不会被拦截的链接 顺序判断
    filterChainDefinitionMap.put("/static/**", "anon");
    //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
    filterChainDefinitionMap.put("/logout", "logout");
    //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
    //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
    filterChainDefinitionMap.put("/**", "authc");
    // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
    shiroFilterFactoryBean.setLoginUrl("/login");
    // 登录成功后要跳转的链接
    shiroFilterFactoryBean.setSuccessUrl("/index");


    //未授权界面;
    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);//散列的次数,如果括号内写2 --散列两次,相当于 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());
    return securityManager;
    }


    /**
     *  开启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;
    }
      @Bean
        public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }


        @Bean
        public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
            return new DefaultAdvisorAutoProxyCreator();
        }
    }

值得注意的是必须加入LifecycleBeanPostProcessor ,DefaultAdvisorAutoProxyCreator这两个bean不然后期做测试时使用@RequiresRoles()会报错。

创建User实体

  1. package com.springboot.shiro.model;
  2. public class User {
  3. private Integer id;
  4. private String name;
  5. private String userName;
  6. private String userPassword;
  7. private String userEmail;
  8. private String userPhone;
  9. private String isDisable;
  10. private String department;
  11. public Integer getId() {
  12. return id;
  13. }
  14. public void setId(Integer id) {
  15. this.id = id;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. public String getUserName() {
  24. return userName;
  25. }
  26. public void setUserName(String userName) {
  27. this.userName = userName;
  28. }
  29.  
  30. public String getUserPassword() {
  31. return userPassword;
  32. }
  33. public void setUserPassword(String userPassword) {
  34. this.userPassword = userPassword;
  35. }
  36. public String getUserEmail() {
  37. return userEmail;
  38. }
  39. public void setUserEmail(String userEmail) {
  40. this.userEmail = userEmail;
  41. }
  42. public String getUserPhone() {
  43. return userPhone;
  44. }
  45. public void setUserPhone(String userPhone) {
  46. this.userPhone = userPhone;
  47. }
  48. public String getIsDisable() {
  49. return isDisable;
  50. }
  51. public void setIsDisable(String isDisable) {
  52. this.isDisable = isDisable;
  53. }
  54. public String getDepartment() {
  55. return department;
  56. }
  57. public void setDepartment(String department) {
  58. this.department = department;
  59. }
  60. }

 

创建HomeController

 

 
  1. package com.springboot.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;


    @Controller
    public class HomeController {
        @RequestMapping("/index")
        public String index(){
            return"/index";
        }


        @RequestMapping("/login")
        public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{
            // 登录失败从request中获取shiro处理的异常信息。
            // shiroLoginFailure:就是shiro异常类的全类名.
            String exception = (String) request.getAttribute("shiroLoginFailure");
            System.out.println("exception=" + exception);
            String msg = "";
            if (exception != null) {
                if (UnknownAccountException.class.getName().equals(exception)) {
                    msg = "账号不存在:";
                } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                    msg = "密码不正确:";
                } else if ("kaptchaValidateFailed".equals(exception)) {
                    msg = "验证码错误";
                } else {
                    msg = "else >> "+exception;
                    System.out.println("else -- >" + exception);
                }
            }
            map.put("msg", msg);
            // 此方法不处理登录成功,由shiro进行处理
            return "/login";
        }


        @RequestMapping("/403")
        public String unauthorizedRole(){
            System.out.println("------没有权限-------");
            return "403";
        }


    }

创建UserController

 

 
  1. package com.springboot.shiro.controller;
    import java.util.ArrayList;
    import java.util.List;


    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authz.annotation.Logical;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;


    @Controller
    @RequestMapping("/user")
    public class UserController {
    @RequestMapping("/login")
        @RequiresRoles(value="admin",logical = Logical.OR)
    public String login(){
    System.out.println("shiwo");
    return "success";
    }
    @RequestMapping("/list")
    public @ResponseBody  List<String> list(){
     Subject subject= SecurityUtils.getSubject();  
       Session session=subject.getSession();  
     List<String> roleList=new ArrayList<String>();  
        if(subject.hasRole("admin")){  
            roleList.add("admin");  
        }  
    return roleList;

    }
    }

创建UserService

  1.  package com.springboot.shiro.service;
  2.  
  3. import java.util.Set;
  4. import com.springboot.shiro.model.User;
  5. public interface UserService {
  6. User getByUserName(String userName);
  7. Set<String> getRoles(String userName);
  8. }

创建UserServiceImpl

  1. package com.springboot.shiro.service.impl;
  2. import java.util.Set;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Service;
  5. import com.springboot.shiro.dao.UserDao;
  6. import com.springboot.shiro.model.User;
  7. import com.springboot.shiro.service.UserService;
  8.  
  9. @Service("userService")
  10.  public class UserServiceImpl implements UserService{
  11. @Autowired
  12. private UserDao userDao;
  13. @Override
  14.  
    public User getByUserName(String userName) {
  15. return userDao.getByUserName(userName);
  16. }
  17. @Override
  18. public Set<String> getRoles(String userName) {
  19. return userDao.getRoles(userName);
  20. }
  21. }

创建UserDao

  1. package com.springboot.shiro.dao;
  2. import java.util.Set;
  3. import org.apache.ibatis.annotations.Mapper;
  4. import com.springboot.shiro.model.User;
  5.  
  6. @Mapper
  7. public interface UserDao {
  8. User getByUserName(String userName);
  9. Set<String> getRoles(String userName);
  10. }

创建UserDao.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.springboot.shiro.dao.UserDao">
  4. <!-- 可根据自己的需求,是否要使用 -->
  5. <resultMap type="com.springboot.shiro.model.User" id="userMap">
  6. <result property="id" column="id"/>
  7. <result property="name" column="name"/>
  8. <result property="userName" column="user_name"/>
  9. <result property="userPassword" column="user_password"/>
  10. <result property="userEmail" column="user_email"/>
  11. <result property="userPhone" column="user_phone"/>
  12. <result property="isDisable" column="isDisable"/>
  13. <result property="department" column="department"/>
  14. </resultMap>
  15. <select id="getByUserName" parameterType="String" resultMap="userMap">
  16. select * from user where name = #{userName}
  17. </select>
  18. <select id="getRoles" parameterType="String" resultType="String">
  19. SELECT `group`.group_name FROM `group`,user,group_user WHERE group_user.group_id=`group`.id
  20. and group_user.user_id = `user`.id and `user`.`name`=#{userName}
  21. </select>
  22. </mapper>

创建index.html

  1. <!DOCTYPE html>
  2. <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
  3. <html>
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Insert title here</title>
  7. </head>
  8. <body>
  9. <button type="button"οnclick="text()">查询</button>
  10. <button type="button"οnclick="update()"class="admin">修改</button>
  11. <button type="button"οnclick="del()"class="admin">删除</button>
  12. </body>
  13. <style>
  14. .admin{
  15. display: none
  16. }
  17. </style>
  18. <script type="text/javascript">
  19. $(function(){
  20. console.log("asd")
  21. $.ajax({
  22. type: "POST",
  23. url: "/user/list"
  24. contentType: "application/json",
  25. success: function(r){
  26. console.log(r)
  27. for(var i=0;i<r.length;i++){
  28. console.log(r[i])
  29. if(r[i]=="admin"){
  30. console.log("admin用户")
  31. $(".admin").css("display","block");
  32. }
  33. }
  34. }
  35. });
  36. })
  37. </script>
  38. </html>

创建错误页面403.html

  1.  <!DOCTYPE html>
  2.  <html>
  3.  <head>
  4.  <meta charset="UTF-8">
  5.  <title>Insert title here</title>
  6.  </head>
  7.  <body>
  8.  权限不足
  9.  </body>
  10.  </html>

创建登录页面login.html

  1.  <!DOCTYPE html>
  2.  <html>
  3.  <head>
  4.  <meta charset="UTF-8">
  5.  <title>Insert title here</title>
  6.  </head>
  7.  <body>
  8.  错误信息:<h4 th:text="${msg}"></h4>
  9.  <form action="" method="post">
  10.  userName:<input type="text" name="username" value="admin"/><br/>
  11.  password:<input type="password" name="password" value="123456"><br/>
  12.  <input type="submit" value="login"/>
  13.  </form>
  14.  </body>
  15.  </html>

这里只做个简单的角色控制 没有涉及到权限控制 如果需要权限控制可以在自定义realm中添加如

  1.     authorizationInfo.setStringPermissions(userService.getPermissions(userName));  

启动项目 输入localhost:8080

如果用户名或者密码错误shiro会自动拦截

如果是admin用户

如果是普通用户

简单的角色验证 

如果是普通用户登录在地址栏输入http://localhost:8080/user/login 会自动跳转权限不足403 页面所以不必担心被人知道路径从而访问数据

posted @ 2020-11-03 13:51  aowumao  阅读(176)  评论(0)    收藏  举报