shiro认证-SSM

pom

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.</version>
</dependency>

web.xml配置

<!-- shiro过滤器定义 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

这五张表生成对应的model、mapper

applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配置自定义的Realm-->
<bean id="shiroRealm" class="com.zhuling.shiro.MyRealm">
<property name="shiroUserService" ref="shiroUserService" />
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
<property name="credentialsMatcher">
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--指定hash算法为MD5-->
<property name="hashAlgorithmName" value="md5"/>
<!--指定散列次数为1024次-->
<property name="hashIterations" value=""/>
<!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
</property>
</bean> <!--注册安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm" />
</bean> <!--Shiro核心过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 身份验证失败,跳转到登录页面 -->
<property name="loginUrl" value="/login"/>
<!-- 身份验证成功,跳转到指定页面 -->
<!--<property name="successUrl" value="/index.jsp"/>-->
<!-- 权限验证失败,跳转到指定页面 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value>
<!--
注:anon,authcBasic,auchc,user是认证过滤器
perms,roles,ssl,rest,port是授权过滤器
-->
<!--anon 表示匿名访问,不需要认证以及授权-->
<!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
<!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->
/user/login=anon
/user/updatePwd.jsp=authc
/admin/*.jsp=roles[admin]
/user/teacher.jsp=perms["user:update"]
<!-- /css/** = anon
/images/** = anon
/js/** = anon
/ = anon
/user/logout = logout
/user/** = anon
/userInfo/** = authc
/dict/** = authc
/console/** = roles[admin]
/** = anon-->
</value>
</property>
</bean> <!-- Shiro生命周期,保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>

ShiroUserService

package com.zhuling.service;

import com.zhuling.model.ShiroUser;

public interface ShiroUserService {
ShiroUser queryByName(String uname); int insert(ShiroUser record);
}

MyRealm

package com.zhuling.shiro;

import com.zhuling.model.ShiroUser;
import com.zhuling.service.ShiroUserService;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource; public class MyRealm extends AuthorizingRealm {
private ShiroUserService shiroUserService; public ShiroUserService getShiroUserService() {
return shiroUserService;
} public void setShiroUserService(ShiroUserService shiroUserService) {
this.shiroUserService = shiroUserService;
} /**
* 授权方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
} /**
* 身份认证方法
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String uname=authenticationToken.getPrincipal().toString();
String pwd=authenticationToken.getCredentials().toString();
ShiroUser shiroUser = shiroUserService.queryByName(uname); AuthenticationInfo info=new SimpleAuthenticationInfo(
shiroUser.getUsername(),
shiroUser.getPassword(),
ByteSource.Util.bytes(shiroUser.getSalt()),
this.getName()
);
return info;
}
}

ShiroUserController

package com.zhuling.controller;
import com.zhuling.model.ShiroUser;
import com.zhuling.service.ShiroUserService;
import com.zhuling.util.PasswordHelper;
import jdk.nashorn.internal.ir.ReturnNode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @Controller
public class ShiroUserController { @RequestMapping("/login")
public String login(HttpServletRequest req, HttpServletResponse resp){
Subject subject = SecurityUtils.getSubject();
String username = req.getParameter("username");
String password = req.getParameter("password");
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
subject.login(usernamePasswordToken);
req.getSession().setAttribute("username",username);
return "main";
} catch (Exception e) {
req.setAttribute("message","用户名密码错误");
return "login";
}
} @RequestMapping("/logout")
public String logout(HttpServletRequest req, HttpServletResponse resp) {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/login.jsp";
} @RequestMapping("/register")
public String register(HttpServletRequest req, HttpServletResponse resp){
String uname = req.getParameter("username");
String pwd = req.getParameter("password");
String salt = PasswordHelper.createSalt();
String credentials = PasswordHelper.createCredentials(pwd, salt); ShiroUser shiroUser=new ShiroUser();
shiroUser.setUsername(uname);
shiroUser.setPassword(credentials);
shiroUser.setSalt(salt);
int insert = shiroUserService.insert(shiroUser);
if(insert>){
req.setAttribute("message","注册成功");
return "login";
}
else{
req.setAttribute("message","注册失败");
return "register";
}
} }

盐加密

盐加密工具类,在做新增用户的时候使用,将加密后的密码、及加密时候的盐放入数据库;

本篇博客中的表数据是现成的,暂时用不上这个工具类去生成数据;

PasswordHelper

package com.zhuling.util;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash; public class PasswordHelper { /**
* 随机数生成器
*/
private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); /**
* 指定hash算法为MD5
*/
private static final String hashAlgorithmName = "md5"; /**
* 指定散列次数为1024次,即加密1024次
*/
private static final int hashIterations = ; /**
* true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储
*/
private static final boolean storedCredentialsHexEncoded = true; /**
* 获得加密用的盐
*
* @return
*/
public static String createSalt() {
return randomNumberGenerator.nextBytes().toHex();
} /**
* 获得加密后的凭证
*
* @param credentials 凭证(即密码)
* @param salt 盐
* @return
*/
public static String createCredentials(String credentials, String salt) {
SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,
salt, hashIterations);
return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();
} /**
* 进行密码验证
*
* @param credentials 未加密的密码
* @param salt 盐
* @param encryptCredentials 加密后的密码
* @return
*/
public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {
return encryptCredentials.equals(createCredentials(credentials, salt));
} public static void main(String[] args) {
//盐
String salt = createSalt();
System.out.println(salt);
System.out.println(salt.length());
//凭证+盐加密后得到的密码
String credentials = createCredentials("", salt);
System.out.println(credentials);
System.out.println(credentials.length());
boolean b = checkCredentials("", salt, credentials);
System.out.println(b);
}
}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>用户登陆</h1>
<div style="color: red">${message}</div>
<form action="${pageContext.request.contextPath}/login" method="post">
帐号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="确定">
<input type="reset" value="重置">
</form>
</body>
</html>

register.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>用户注册</h1>
<div style="color: red">${message}</div>
<form action="${pageContext.request.contextPath}/register" method="post">
帐号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="注册">
<input type="button" οnclick="location.href='${pageContext.request.contextPath}/login.jsp'" value="返回">
</form>
</body>
</html>

main.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="r" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>主界面<%=System.currentTimeMillis()%>,欢迎您:[${sessionScope.username}]</h1>
<ul>
系统功能列表
<li>
<a href="admin/addUser.jsp">用户新增</a>
</li>
<li>
<a href="admin/listUser.jsp">用户查询</a>
</li>
<li>
<a href="admin/resetPwd.jsp">重置用户密码</a>
</li>
<li>
<a href="admin/updateUser.jsp">用户修改</a>
</li>
<li>
<a href="user/updatePwd.jsp">个人密码修改</a>
</li>
<li>
<a href="user/teacher.jsp">老师简介</a>
</li>
<li>
<a href="${pageContext.request.contextPath}/logout">退出系统</a>
</li>
</ul>
<ul>
shiro标签
<li>
<r:hasPermission name="user:create">
<a href="admin/addUser.jsp">用户新增</a>
</r:hasPermission>
</li>
<li>
<a href="admin/listUser.jsp">用户查询</a>
</li>
<li>
<a href="admin/resetPwd.jsp">重置用户密码</a>
</li>
<li>
<r:hasPermission name="user:update">
<a href="admin/updateUser.jsp">用户修改</a>
</r:hasPermission>
</li>
<li>
<a href="user/updatePwd.jsp">个人密码修改</a>
</li>
<li>
<a href="${pageContext.request.contextPath}/logout">退出系统</a>
</li>
</ul>
</body>
</html>

shiro认证-SSM的更多相关文章

  1. Shiro集成SSM基于URL权限管理(一)

    学习了shiro之后,我们就可以说尝试把shiro加入ssm中,并做一套基于URL的权限管理. 其他的准备工作就不多说了,直接动手操作,看到效果再去理解. 表结构 执行如下,数据库名字可以自行修改,不 ...

  2. Apache Shiro 使用手册(二)Shiro 认证

    认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的"实体/凭证"组合便是&quo ...

  3. Apache Shiro 认证过程

    3.1.1    示例 Shiro验证Subjects 的过程中,可以分解成三个不同的步骤: 1. 收集Subjects 提交的Principals(身份)和Credentials(凭证): 2. 提 ...

  4. shiro认证登录实现

    准备工作: 在web.xml中配置shiro核心过滤器 在spring配置文件中提供核心过滤器运行所需要的辅助bean对象,在对象内注入安全管理器 拦截认证 配置三个url 拦截除了登录页面以及认证a ...

  5. 【shiro】(4)---Shiro认证、授权案例讲解

    Shiro认证.授权案例讲解 一.认证  1. 认证流程     2.用户密码已经加密.加盐的用户认证 (1)测试类 // 用户登陆和退出,这里我自定了一个realm(开发肯定需要自定义realm获取 ...

  6. 无状态shiro认证组件(禁用默认session)

    准备内容 简单的shiro无状态认证 无状态认证拦截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.st ...

  7. 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权

    原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...

  8. [Shiro] - shiro之SSM中的使用

    在学习shiro的途中,在github发现了一个开源项目,所需的控件刚好是自己要学习的方向. 虽然还要学习完ssm的shiro与springboot的shiro,以及接下来的种种控件和类库,但学习这个 ...

  9. frame shiro 认证示例及原理简述

    shiro 认证流程 1.创建一个 javaSE 的maven项目(quickstart),并添加依赖 <dependency> <groupId>junit</grou ...

随机推荐

  1. Hadoop的理解笔记

    1.2Hadoop与云计算的关系1.什么是云计算:一种基于互联网的计算,在其中共享的资源.软件和信息以一种按需的方式提供给计算机和设备 , 就如同日常生活中的电网一样. 什么是Hadoop:Hadoo ...

  2. python中检测某个变量是否有定义

    目录 第一种方法使用内置函数locals() 第二种方法使用内置函数dir() 第三种方法使用内置函数vars() 第一种方法使用内置函数locals() 'testvar' in locals(). ...

  3. 使用QSaveFile类安全的读写文件(继承自QFileDevice,与QFile并列)

    QSaveFile类也是一种I/O设备,来用来读写文本文件和二进制文件,但使用该类的话,在写入操作失败时不会导致已经存在的数据丢失. 该类在执行写操作时,会先将内容写入到一个临时文件中,如果没有错误发 ...

  4. jacascript Date 学习

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! Date dateObject.getDate();  返回一个月中的某一天(1-31) dateObje ...

  5. (八)shiro之jdbcRealm

    pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...

  6. C# Unix时间戳和DateTime类型相互转换

    /// <summary> /// 将Unix时间戳转换为DateTime类型时间 /// </summary> /// <param name="d" ...

  7. reactnative中FlatList上拉加载更多的解决办法

    项目app中用到了list滚动加载,把List做了下对比发现FlatList比较适合自己的项目,但是在实际运用中 onEndReached方法需要给定 onEndReachedThreshold的高度 ...

  8. kong网关命令(一)

    上次在虚拟机里安装kong网关后,因为版本(1.4)太高,目前Kong Dashboard无法支持, 后续发现Git上有个开源工具Kong admin ui,下载源码并部署到NGINX. 但是发现使用 ...

  9. SQL中新建注释、查询注释和说明

    1.查询注释 SELECT A.name AS table_name, B.name AS column_name, C.value AS column_description FROM sys.ta ...

  10. ffmpeg 命令的使用

    当然先安装了 gentoo 下一条命令搞定 emerge  ffmpeg 格式转换 (将file.avi 转换成output.flv) ffmpeg -i  file.avi  output.flv ...