shiro实战(1)--web

目录结构:

 

 

 数据库结构:

 

 

 一·web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>shiro_web</display-name>
  <listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>shiroEnvironmentClass</param-name>
    <param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
  </context-param>
  <context-param>
    <param-name>shiroConfigLocations</param-name>
    <param-value>classpath:shiro.ini</param-value>
  </context-param>
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

二·shiro.ini

[main]
#使用数据库验证授权
databaseRealm=com.yuanbo.DatabaseRealm
securityManager.realms=$databaseRealm
#配置一个url拥有多个role
roles=com.yuanbo.CustomRolesAuthorizationFilter
#没有验证的情况
authc.loginUrl=/login.jsp
#没有角色的情况
roles.unauthorizedUrl=/noRoles.jsp
#没有权限的情况
perms.unauthorizedUrl=/noPerms.jsp
#数据库中取得,不需要配置
[users]
[urls]
/doLogout=logout
#可以匿名访问
/login.jsp=anon
/noRoles.jsp=anon
/noPerms.jsp=anon
#登录后才能查看
/listProduct.jsp=authc
/deleteProduct.jsp=authc,roles[admin,productManager]
/deleteOrder.jsp=authc,perms["deleteOrder"]

三·实体类

package com.yuanbo;

public class User {
    private int id;
    private String name;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int 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;
    }

}

四·DB

package com.yuanbo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

public class Dao {
    public Dao() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/shiro?serverTimezone=UTC", "root",
                "123456");
    }

    public String getPassword(String userName) {
        String sql = "select password from user where name = ?";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {

            ps.setString(1, userName);

            ResultSet rs = ps.executeQuery();

            if (rs.next())
                return rs.getString("password");

        } catch (SQLException e) {

            e.printStackTrace();
        }
        return null;
    }

    public Set<String> listRoles(String userName) {

        Set<String> roles = new HashSet<>();
        String sql = "select r.name from user u " + "left join user_role ur on u.id = ur.uid "
                + "left join Role r on r.id = ur.rid " + "where u.name = ?";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
            ps.setString(1, userName);
            ResultSet rs = ps.executeQuery();

            while (rs.next()) {
                roles.add(rs.getString(1));
            }

        } catch (SQLException e) {

            e.printStackTrace();
        }
        return roles;
    }

    public Set<String> listPermissions(String userName) {
        Set<String> permissions = new HashSet<>();
        String sql = "select p.name from user u " + "left join user_role ru on u.id = ru.uid "
                + "left join role r on r.id = ru.rid " + "left join role_permission rp on r.id = rp.rid "
                + "left join permission p on p.id = rp.pid " + "where u.name =?";

        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {

            ps.setString(1, userName);

            ResultSet rs = ps.executeQuery();

            while (rs.next()) {
                permissions.add(rs.getString(1));
            }

        } catch (SQLException e) {

            e.printStackTrace();
        }
        return permissions;
    }

    public static void main(String[] args) {
        System.out.println(new Dao().listRoles("zhang3"));
        System.out.println(new Dao().listRoles("li4"));
        System.out.println(new Dao().listPermissions("zhang3"));
        System.out.println(new Dao().listPermissions("li4"));
    }
}

五·realm

package com.yuanbo;

import java.util.Set;

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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class DatabaseRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();
        Set<String> permissions = new Dao().listPermissions(userName);
        Set<String> roles = new Dao().listRoles(userName);
        SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
        s.setStringPermissions(permissions);
        s.setRoles(roles);
        return s;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken t = (UsernamePasswordToken) token;
        //String userName = token.getPrincipal().toString();
        String userName =new String(t.getUsername());
        String password = new String(t.getPassword());
        
        String passwordInDB = new Dao().getPassword(userName);
        
        if(passwordInDB == null || !passwordInDB.equals(password))
            throw new AuthenticationException();
        
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,password,getName());
        return info;
    }

}

六·过滤器(一个url多个roles访问)

package com.yuanbo;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

public class CustomRolesAuthorizationFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {
        Subject subject = getSubject(req, resp);  
        String[] rolesArray = (String[]) mappedValue;  
  
        if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问  
            return true;  
        }  
        for (int i = 0; i < rolesArray.length; i++) {  
            if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问  
                return true;  
            }  
        }  
  
        return false;
    }

}

七·servlet

package com.yuanbo;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

/**
 * Servlet implementation class LoginServlet
 */
@WebServlet(name = "loginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);

        try {
            subject.login(token);
            Session session = subject.getSession();
            session.setAttribute("subject", subject);
            
            response.sendRedirect("index.jsp");
        } catch (AuthenticationException e) {
            request.setAttribute("error","验证失败");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }

}

八·index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css"/>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
    <div class="loginDiv">
        <c:if test="${empty subject.principal }">
            <a href="login.jsp">login</a><br>
        </c:if>
        <c:if test="${!empty subject.principal }">
            <span class="desc">hello,${subject.principal }!</span><br>
            <a href="doLogout">logout</a>
        </c:if>
        <br>
        <a href="listProduct.jsp">query product</a><span class="desc">(登录后才能查看)</span><br>
        <a href="deleteProduct.jsp">delete product</a><span class="desc">(需要产品管理员角色)</span><br>
        <a href="deleteOrder.jsp">delete order</a><span class="desc">(需要删除订单权限)</span><br>
    </div>
</div>
</body>
</html>

九·login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <div class="workingroom">
        <div class="errorInfo">${error }</div>
        <form action="login" method="post">
            account:   <input type="text" name="userName" /><br>
            password:  <input type="password" name="password"/><br>
            <br>
            <input type="submit" value="login">
            <div>
                <span class="desc">账号:zhang3 密码:12345 角色:admin</span><br>
                <span class="desc">账号:li4 密码:abcde 角色:productManager</span><br>
        </div>
        </form>
    </div>
</body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
    listProduct.jsp ,能进来,就表示已经登录成功了
    <br>
    <a href="#" onclick="javascript:history.back()">return</a>
</div>
</body>
</html>

十一

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
 
    deleteProduct.jsp,能进来<br>就表示拥有 productManager 角色
    <br>
    <a href="#" onClick="javascript:history.back()">返回</a>
</div>
</body>
</html>

十二

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
 
    deleteOrder.jsp ,能进来,就表示有deleteOrder权限
    <br>
    <a href="#" onClick="javascript:history.back()">返回</a>
</div>
</body>
</html>

十三

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
 
    权限不足
    <br>
    <a href="#" onClick="javascript:history.back()">返回</a>
</div>
</body>
</html>

十四

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<link rel="stylesheet" type="text/css" href="static/css/style.css" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="workingroom">
 
    角色不匹配
    <br>
    <a href="#" onClick="javascript:history.back()">返回</a>
</div>
</body>
</html>

最后,推荐一个java学习平台吧,感觉挺不错的,写得挺细的,还有问答,可以解疑

https://how2j.cn/k/shiro/shiro-web/1722.html?p=81485

posted @ 2019-11-18 17:16  勤俭的搬运工  阅读(137)  评论(0编辑  收藏  举报