springboot整合shiro进行身份验证和授权

一、引入shiro依赖:

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.shiro</groupId>
 5     <artifactId>wangyao</artifactId>
 6     <packaging>war</packaging>
 7     <version>0.0.1-SNAPSHOT</version>
 8     <name>wangyao Maven Webapp</name>
 9     <url>http://maven.apache.org</url>
10     <!--启动父依赖 -->
11     <parent>
12         <groupId>org.springframework.boot</groupId>
13         <artifactId>spring-boot-starter-parent</artifactId>
14         <version>1.5.6.RELEASE</version>
15     </parent>
16     <properties>
17         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18         <java.version>1.8</java.version>
19         <sqlserver-connector>4.0</sqlserver-connector>
20     </properties>
21     <dependencies>
22         <!--spring 基本的web服务 -->
23         <dependency>
24             <groupId>org.springframework.boot</groupId>
25             <artifactId>spring-boot-starter-web</artifactId>
26         </dependency>
27         <!--thmleaf模板依赖. -->
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-thymeleaf</artifactId>
31         </dependency>
32         <!-- shiro spring. -->
33         <dependency>
34             <groupId>org.apache.shiro</groupId>
35             <artifactId>shiro-spring</artifactId>
36             <version>1.3.2</version>
37         </dependency>
38         <!-- Spirng data JPA依赖; -->
39        <dependency>
40            <groupId>org.springframework.boot</groupId>
41            <artifactId>spring-boot-starter-data-jpa</artifactId>
42        </dependency>
43        <!-- sqlserver依赖 -->
44         <dependency>
45             <groupId>com.microsoft.sqlserver</groupId>
46             <artifactId>sqljdbc4</artifactId>
47             <version>${sqlserver-connector}</version>
48         </dependency>
49         <dependency>
50             <groupId>org.springframework.boot</groupId>
51             <artifactId>spring-boot-devtools</artifactId>
52             <optional>true</optional>
53         </dependency>
54         <dependency>
55             <groupId>junit</groupId>
56             <artifactId>junit</artifactId>
57             <version>3.8.1</version>
58             <scope>test</scope>
59         </dependency>
60     </dependencies>
61     <build>
62         <finalName>wangyao</finalName>
63     </build>
64 </project>

二、shiro配置:

 1 package shiropro.config;
 2 
 3 import java.util.LinkedHashMap;
 4 import java.util.Map;
 5 
 6 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
 7 import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
 8 import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
 9 import org.springframework.context.annotation.Bean;
10 import org.springframework.context.annotation.Configuration;
11 import org.apache.shiro.mgt.SecurityManager;
12 import shiropro.shiro.MyShiroRealm;
13 
14 /**
15  * shiro配置
16  * 
17  * @author wangyao
18  *
19  */
20 @Configuration
21 public class ShiroConfiguration {
22     @Bean
23     public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
24         System.err.println("ShiroConfiguration.shirFilter()");
25         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
26         // 必须设置 SecurityManager
27         shiroFilterFactoryBean.setSecurityManager(securityManager);
28         // 拦截器.
29         Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
30 
31         // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
32         shiroFilterFactoryBean.setLoginUrl("/login");
33         // 登录成功后要跳转的链接
34         shiroFilterFactoryBean.setSuccessUrl("/index");
35         // 未授权界面;
36         shiroFilterFactoryBean.setUnauthorizedUrl("/403");
37 
38         // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
39         filterChainDefinitionMap.put("/logout", "logout");
40         filterChainDefinitionMap.put("/add", "perms[权限添加]");
41         filterChainDefinitionMap.put("/del", "perms[权限删除]");
42         // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
43         // <!-- authc 表示需要认证才能访问的页面 -->
44         filterChainDefinitionMap.put("/**", "authc");
45         shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
46         System.out.println("Shiro拦截器工厂类注入成功");
47         return shiroFilterFactoryBean;
48     }
49 
50     /**
51      * 身份认证realm; (这个需要自己写,账号密码校验;权限等)
52      * 
53      * @return
54      */
55     @Bean
56     public MyShiroRealm myShiroRealm() {
57         MyShiroRealm myShiroRealm = new MyShiroRealm();
58         return myShiroRealm;
59     }
60 
61     @Bean
62     public SecurityManager securityManager() {
63         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
64         // 设置realm.
65         securityManager.setRealm(myShiroRealm());
66         return securityManager;
67     }
68 
69     /**
70      * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持,调用授权的方法必须要有此支持;
71      * 
72      * @param securityManager
73      * @return
74      */
75 
76     @Bean
77     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
78         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
79         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
80         return authorizationAttributeSourceAdvisor;
81     }
82 
83 }

三、shiro身份校验(继承AuthorizingRealm):

 1 package shiropro.shiro;
 2 
 3 
 4 import java.util.HashSet;
 5 import java.util.Map;
 6 import java.util.Set;
 7 
 8 import javax.annotation.Resource;
 9 
10 import org.apache.shiro.authc.AuthenticationException;
11 import org.apache.shiro.authc.AuthenticationInfo;
12 import org.apache.shiro.authc.AuthenticationToken;
13 import org.apache.shiro.authc.SimpleAuthenticationInfo;
14 import org.apache.shiro.authc.UsernamePasswordToken;
15 import org.apache.shiro.authz.AuthorizationInfo;
16 import org.apache.shiro.authz.SimpleAuthorizationInfo;
17 import org.apache.shiro.realm.AuthorizingRealm;
18 import org.apache.shiro.subject.PrincipalCollection;
19 
20 import shiropro.entity.UserInfo;
21 import shiropro.service.IUserInfoService;
22 /**
23  * shiro身份校验
24  * 
25  * @author wangyao
26  *
27  */
28 public class MyShiroRealm extends AuthorizingRealm {
29 
30     @Resource
31     private IUserInfoService userInfoService;
32 
33     /**
34      * 认证信息.(身份验证) : Authentication 是用来验证用户身份
35      * 
36      * @param token
37      * @return
38      * @throws AuthenticationException
39      */
40     @Override
41     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
42         System.err.println("MyShiroRealm.doGetAuthenticationInfo()");
43         UsernamePasswordToken tk=(UsernamePasswordToken) token;
44         // 获取用户的输入的账号.
45         String username =  tk.getUsername();
46         //获取用户输入的密码
47         //String pwd=new String(token.getPassword());
48         // 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
49         UserInfo userInfo = userInfoService.findByUsername(username);
50         //密码可以加密在此
51         System.out.println("----->>userInfo=" + userInfo);
52         if (userInfo == null) {
53             return null;
54         }
55         SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userInfo, // 用户名
56                 userInfo.getPassword(), // 密码
57                 getName() // realm name
58         );
59 
60         return authenticationInfo;
61     }
62     /**
63      * 获取授权信息(包含权限信息)
64      */
65     @Override
66     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
67         UserInfo user=(UserInfo) getAvailablePrincipal(pc);
68         System.err.println("授权:"+user);
69         String loginName= user.getUsername();
70         if (loginName != null) {
71             SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
72             Map<String,Object> map=user.getPerList();
73             //用户的角色信息
74             /*List<String> roles=(List<String>) map.get("roles");
75             for (String role : roles) {
76                 info.addRole(role);
77             }*/
78             Set<String> roleSet=new HashSet<String>(); 
79             roleSet.add("100002");
80             info.setRoles(roleSet);
81             //用户的权限信息
82             /*List<String> permissions=(List<String>) map.get("permissions");
83             for (String permission : permissions) {
84                 info.addStringPermission(permission);
85             }*/
86             Set<String> permissionSet =new HashSet<String>(); 
87             permissionSet.add("权限添加");
88             info.setStringPermissions(permissionSet);
89             return info;
90         }
91         return null;
92     }
93 
94 
95 }

四、控制层:

package shiropro.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeAction {

    @GetMapping("/index")
    public String index() {
        return "index";
    }

    @PostMapping("/del")
    public String del() {
        return "del";
    }

    @PostMapping("/add")
    public String add() {
        return "add";
    }

    @GetMapping("/login")
    public String lo() {
        return "login";
    }

    // 登录提交地址和applicationontext-shiro.xml配置的loginurl一致。 (配置文件方式的说法)
    @PostMapping("/login")
    public String login(HttpServletRequest request, Map<String, Object> map) throws Exception {
        System.out.println("HomeController.login()");
        // 登录失败从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)) {
                System.out.println("UnknownAccountException -- > 账号不存在:");
                msg = "UnknownAccountException -- > 账号不存在:";
            } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                System.out.println("IncorrectCredentialsException -- > 密码不正确:");
                msg = "IncorrectCredentialsException -- > 密码不正确:";
            } else if ("kaptchaValidateFailed".equals(exception)) {
                System.out.println("kaptchaValidateFailed -- > 验证码错误");
                msg = "kaptchaValidateFailed -- > 验证码错误";
            } else {
                msg = "else >> " + exception;
                System.out.println("else -- >" + exception);
            }
        }
        map.put("msg", msg);
        // 此方法不处理登录成功,由shiro进行处理.
        return "index";
    }

//-----------------------------------------------------------------------------------------------------------
    
    public static void main(String[] args) {
        List<Integer> a = new ArrayList<>();
        List<Integer> b = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            if (i % 2 == 0) {
                a.add(i);
            }
            if (i % 3 == 0) {
                b.add(i);
            }
        }

        List<Integer> list = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        System.out.println("a.size:" + a.size() + ".....b.size:" + b.size());
        long s = System.currentTimeMillis();
        // for (Integer i : a) {
        // map.put(i.toString(), i);
        // }
        // System.out.println(map.size());
        // for (Integer in : b) {
        // if(map.get(in.toString())!=null){
        // list.add(in);
        // }
        // }

        // list.addAll(a);list.addAll(b);
        System.out.println("-------list:" + list.size());
        System.out.println("------------------");
        // List<Integer> list2=new ArrayList<>();
        // Set<Integer> set=new HashSet<>();
        // set.addAll(list);
        // for (Integer integer : set) {
        // list2.add(integer);
        // }
        // System.out.println("-------list2:"+list2.size());
        // list.removeAll(list2);
        // System.out.println("----------------0");
        for (Integer m : a) {
            //if (m <= 1000) {
                if (m % 3 == 0) {
                    list.add(m);
                }
            //}
        }
        long e = System.currentTimeMillis();
        System.out.println(e - s + "......." + list.size());
    }
}

五、login页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
    错误信息:
    <h4 th:text="${msg}"></h4>
    <form action="/login" 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>

2017-09-01 15:39:45

posted @ 2017-09-01 15:40  wanglittlehandsome  阅读(792)  评论(0编辑  收藏  举报