ssm+shiro 基础的配置文件,
application-jdbc.xml
<context:property-placeholder location="classpath:*.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
<property name="typeAliasesPackage" value="com.paopao.pojo"></property>
</bean>
<!-- 扫描mapper通过代理机制为借口创建一个实现类对象(代理对象)
多个数据源需要设置多个basepackage
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.paopao.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
application-service.xml
<!-- 扫描包 -->
<context:component-scan base-package="com.paopao"/>
<!-- 注解事务 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- aop注解 -->
<aop:aspectj-autoproxy/>
application-servlet.xml
<!-- 注解驱动 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/html/"/>
<property name="suffix" value=".html"></property>
</bean>
<!-- 不拦截静态资源 -->
<mvc:default-servlet-handler/>
<!-- 定义文件上传解析器 -->
<bean id="" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="5242880"></property>
</bean>
application-shiro.xml
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/login.html"/>
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
<property name="successUrl" value="/show"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 权限配置 -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何权限即可访问 -->
/static/**=anon
/user/login=anon
/user/registry=anon
/login=anon
<!-- perms[user:query]表示访问此连接需要权限为user:query的用户 -->
/user=perms[user:query]
<!-- roles[manager]表示访问此连接需要用户的角色为manager -->
/user/add=roles[manager]
/user/del/**=roles[admin]
/user/edit/**=roles[manager]
<!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login-->
/** = authc
</value>
</property>
</bean>
<!--安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"></property>
</bean>
<!--登录验证管理-->
<bean id="myRealm" class="com.paopao.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" ></property>
</bean>
<!--密码加密的规则-->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5"></property>
<property name="hashIterations" value="122"></property>
</bean>
<!-- 注解权限 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/all?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc.username=root
jdbc.password=root
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" version="3.1">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>static/html/index.html</welcome-file>
</welcome-file-list>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 前段控制器 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Shiro配置 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
首先配置myRealm继承AuthorizingRealm实现认证和权限的方法
package com.paopao.shiro;
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
try {
authorizationInfo.setRoles(userService.getRoleByName(username));
authorizationInfo.setStringPermissions(userService.getMenuByName(username));
}catch (Exception e){
}
return null;
}
/**
* 认证
* */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
User user = userService.getByName(username);
if (StringUtils.isEmpty(user))
throw new MyException("账号密码错误");
if (user.getState() != 1)
throw new MyException("账号锁定");
//加盐散列,然后比对数据库的密码
String password = user.getPassword();
ByteSource salt = ByteSource.Util.bytes(user.getSalt());
AuthenticationInfo info = new SimpleAuthenticationInfo(username,password,salt, getName());
return info;
}
}
写个登陆页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="./user/login" method="post">
username:<input type="text" name="username" value=""><br>
password:<input type="password" name="password" value="">
<input type="submit" value="save">
</form>
<hr>
<form action="./user/registry" method="post">
username:<input type="text" name="username" value=""><br>
password:<input type="password" name="password" value="">
<input type="submit" value="save">
</form>
</body>
</html>
视图层
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/get/{id}")
public User get(@PathVariable int id) {
System.out.println("come");
return userService.getUser(id);
}
/**
* 登陆
* */
@RequestMapping("/login")
public ResultUtil login(@RequestParam String username,
@RequestParam String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
} catch (Exception e) {
return ResultUtil.getERR(201, e.getMessage());
}
return ResultUtil.getOK();
}
/**
* 注册
*/
@RequestMapping("/registry")
public ResultUtil register(@RequestParam String username,
@RequestParam String password) {
//加密
String salt = UUID.randomUUID().toString();
ByteSource sqlt =ByteSource.Util.bytes(salt);
//散列次数要和配置文件里的一样 ==122次,
String pass = new SimpleHash("MD5", password,sqlt,122).toHex();
User user = new User();
try {
user.setUsername(username);
user.setPassword(pass.toString());
user.setSalt(salt);
user.setState(1);
user.setCreated(new Date());
user.setModified(new Date());
userService.addUser(user);
} catch (Exception e) {
return ResultUtil.getERR(201, e.getMessage());
}
return ResultUtil.getOK();
}
}
service层
public interface UserService {
/** 测试*/
User getUser(int id);
/** 根据用户名查询用户*/
User getByName(String username);
/** 根据用户名查询用户角色*/
Set<String> getRoleByName(String username);
/** 根据用户名查询用户权限*/
Set<String> getMenuByName(String username);
/** 添加用户*/
void addUser(User user);
}
启动tomcat,
a.png
注册admin,,然后登陆
b.png
权限采用注解方式,Article做测试
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleMapper articleMapper;
@RequiresPermissions("user:select") //权限
@Override
public Article getArticle(int id) {
return articleMapper.getById(id);
}
@LogAnnotation(corapation = "查询所有")
@RequiresRoles("admin") //角色
public List<Article> getList() {
return articleMapper.getList();
}
}
访问getlist,无法拿到数据,没有权限
c.png
实现注解方式的aop
声明日志注解类
/**
* 自定义注解
* */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogAnnotation {
String corapation() default "";
}
切面类
/**
* 日志切面
*/
@Component
@Aspect
public class LogAspect {
@Pointcut("@annotation(com.paopao.annotation.LogAnnotation)")
public void pointcut() {
}
/**
* 注解实现日至切面
* 前: 获取当前用户
* 后: 获取方法的注解参数
*/
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
String user = (String) SecurityUtils.getSubject().getPrincipal();
Object object = null;
System.out.println("前--" + user);
try {
object = point.proceed();
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行方法错误");
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName());
String zhujie = method.getAnnotation(LogAnnotation.class).corapation();
System.out.println("后--" + zhujie);
return object;
}
}
在上面的getlist方法已经加了注解.然后给admin一个admin权限,访问加注解的方法
打印
d.png
总结:
ssm基本整合
spring的注解实现AOP
集成shiro












网友评论