SSM+Shiro:
1.利用IDEA快速创建SpringMVC环境
2.整合Spirng
⑴Web.xml中添加相关配置:
使用IDEA直接创建SpringMVC项目的话,不用再执行这一步,因为IDEA已经将spring和springmvc都整合进来.对于配置文件,默认是applicationContext.xml,在WEB-INF下,如果修改,可如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
⑵在applicationContext.xml中添加相关的配置:
包扫描,数据源,数据事务管理,annotation-driven,创建相应的文件结构,bean包,
<context:component-scan base-package="com.dong.*">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 配置数据源 -->
<bean id = "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.Driver}"></property>
<property name="jdbcUrl" value="${jdbc.uri}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxPoolSize" value="500"></property>
</bean>
<!-- 事务管理 -->
<bean id = "DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启基于注解的事务-->
<tx:annotation-driven transaction-manager="DataSourceTransactionManager"></tx:annotation-driven>
3.整合SpringMVC
⑴在dispatcher-servlet.xml中配置视图解析器(用于对返回的视图名添加前缀和后缀),包扫描(用于扫描映射类),mvc:annotation-driven,用于兼容,mvc:default-servlet-handler:用于直接访问静态资源
<!-- Spring MVC 只负责网站的跳转逻辑 -->
<!-- 只扫描controller 组件 -->
<context:component-scan base-package="com.dong.*" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven ></mvc:annotation-driven>
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
注意:这里的dispatcher-servlet.xml如果没有指定,则使用默认的serlvetname-servlet.xml,如想指定:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher.xml</param-value>
</init-param>
</servlet>
4.整合Mybatis
⑴导入Jar包
⑵在spring的配置文件applicationContext.xml中进行配置:sqlSessionFactory,扫描mapper的映射路径,
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:config.xml"></property>
<property name="mapperLocations" value="classpath:com/dong/mapper/*.xml"></property>
</bean>
<mybait-spring:scan base-package="com.dong.dao"></mybait-spring:scan>
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dong.dao"></property>
</bean>
注意,这里需要在类路径下创建mybatis的配置文件,config.xml,也可以不用配置,但是在开发中尽量配置,同时,需要指定mapper.xml的映射路径
5.整合Shiro
⑴导入jar包,(主要是后7个jar,前几个是因为在项目中开发报错,提示该添加的jar)
⑵在web.xml中添加过滤器
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<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>
⑶在applicationContext.xml中添加shiro的相关配置:realm,credentialsMatcher(非必须),缓存lifecycleBeanPostProcessorsecurityManager,shiroFilter.
<bean id="myRealm" class="com.dong.realm.myrealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5" />
<property name="hashIterations" value="1024" />
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<!-- 配置 Bean 后置处理器: 会自动的调用和 Spring 整合后各个组件的生命周期方法. -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 启用shrio授权注解拦截方式 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 装配 securityManager -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置登陆页面 -->
<property name="loginUrl" value="index.jsp"/>
<!-- 登陆成功后的一面 -->
<property name="successUrl" value="/views/success.jsp"/>
<property name="unauthorizedUrl" value="/views/unauthorized.jsp"/>
<!-- 具体配置需要拦截哪些 URL, 以及访问对应的 URL 时使用 Shiro 的什么 Filter 进行拦截. -->
<property name="filterChainDefinitions">
<value>
/index.jsp=anon
/views/success.jsp=anon
/logout = logout
/images/** =anon
/js/** = anon
/styles/** = anon
</value>
</property>
</bean>
⑷创建自定义的realm,并实现相应的认证和授权方法
package com.dong.realm;
import com.dong.service.userService2;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class myrealm extends AuthorizingRealm {
@Autowired
userService2 userService2;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
System.out.println("----------->doGetAuthenticationInfo" + authenticationToken);
//1.把AuthenticationToken类型的参数转换为UsernamePasswordToken类型
UsernamePasswordToken usernamePasswordToken =(UsernamePasswordToken) authenticationToken;
//2.从UsernamePasswordToken 中获取username
String username = usernamePasswordToken.getUsername();
System.out.println(userService2.getpassword(username));
//3.调用数据库,获取username对应的记录
System.out.println("------------------>从数据库中获取username:" + username + "用户所对应的信息");
String check = userService2.checkusername(username);
System.out.println(check.toString());
//4.若用户不存在,抛异常
if( check.equals("null")){
throw new UnknownAccountException("用户不存在");
}
//5.根据用户信息的情况,决定是否需要抛出其他AuthenticationToken异常
if("monster".equals(username)){
throw new LockedAccountException("用户被锁定");
}
//6.根据用户情况,构建AuthenticationInfo对象并返回.通常使用的实现类为:SimpleAuthenticationInfo
//以下信息是从数据库中获取:
//1.princial:认证的实体信息, 可以是username,也可以是数据库中对应的实体
Object principal = username;
//2.从数据表中获取的密码
//没有使用salt
// Object credentials = 123456;
//使用salt
//3.realmName:当前realm对象的name,调用父类的getName()方法即可.
String realName = getName();
// SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,credentials,realName);
//4.盐值
//加入salt后,需要使用的info
ByteSource credentialssalt = ByteSource.Util.bytes(username);
Object credentials = userService2.getpassword(username);
String hashAlgorithmName = "MD5";
int hashIterations = 1024;
Object result = new SimpleHash(hashAlgorithmName,credentials,credentialssalt,hashIterations);
System.out.println("加密后的密码:" + result.toString());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,result,credentialssalt,realName);
System.out.println("welcom role:" + userService2.getrole(username));
return info;
}
}
注意:这里的userservice是service层的方法,在调用方法的时候可以注入,并进行验证。
6.实现相关业务(用户认证)
⑴创建index.jsp,实现账号和密码的输入
<table>
<form action="shiroLogin" method="post">
<tr>
<td><B>你好 : 朋友 </B>
<td>账号: <input type="text" name="username"> </td>
<td>密码:<input type="password" name="password"></td>
<td> <input type="submit" value="登录"> </td>
</form>
<td> <a style="text-decoration: none" href="toregistered">注册 </a> </td>
</tr>
</table>
⑵创建控制器,并配置hall.jsp(略,hall.jsp随便定义)
package com.dong.controller;
import com.dong.service.userService2;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class shiroController {
@RequestMapping("/shiroLogin")
public String login(@RequestParam("username") String username, @RequestParam("password") String password){
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
currentUser.login(token);
System.out.println("登录成功");
return "hall";
} catch (AuthenticationException ae) {
System.out.println("登录失败 :" + ae.getMessage());
}
}
return "redirect:index.jsp";
}
}
注意:这里暂时将登陆的验证信息显示在后台,
⑶在realm的实现类中进行相应的修改,注入userService,其中的用户检测,获取密码都是通过userservice实现对dao层的调用,来查询数据库,这块咱们的realm不变,因为前面已经导入usreService
⑷创建service层,提供调用接口
package com.dong.service;
import com.dong.dao.userdao2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class userService2 {
@Autowired
private userdao2 mapper;
public String getpassword(String username){
return mapper.getuserpassword(username);
}
public String checkusername(String username){
return mapper.checkusername(username);
}
}
⑸创建mapper对象,即首先创建方法的接口类
package com.dong.dao;
import org.springframework.stereotype.Component;
@Component
public interface userdao2 {
public String getuserpassword(String username);
public String checkusername(String username);
}
⑹创建mapper配置文件,mapper放置在applicationContext.xml中进行配置的mapper扫描路径下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-Mapper.dtd">
<!-- 名称空间 ,可以随便写,但是如果使用接口,则需要指定为接口的全类名,-->
<mapper namespace="com.dong.dao.userdao2">
<select id="getuserpassword" resultType="String">
SELECT PASSWORD
FROM USER
WHERE Account = #{username}
</select>
<select id="checkusername" resultType="String">
SELECT Account
FROM USER
WHERE Account =#{username}
</select>
</mapper>
最后:注意数据库表的创建,注意在本例中,我们只用到用户名和密码,所以在测试中,可以随便创建一张user表,只要有用户名和密码即可.
在案例的实际效果展示:(这个是本人最近在做的一个项目的一部分)
声明:我们的数据表中有一个用户: username: admin ,password: 123456
输入正确的密码后台结果为:(打印的这些信息都是在程序中的设置的输入输出,为了方便查看效果)
当输入错误的密码:
谢谢观看,如有问题,敬请指出,与君共勉