ssm+shiro 基礎(chǔ)的配置文件,
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通過代理機(jī)制為借口創(chuàng)建一個(gè)實(shí)現(xiàn)類對(duì)象(代理對(duì)象)
多個(gè)數(shù)據(jù)源需要設(shè)置多個(gè)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"/>
<!-- 注解事務(wù) -->
<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
<!-- 注解驅(qū)動(dòng) -->
<mvc:annotation-driven/>
<!-- 視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/html/"/>
<property name="suffix" value=".html"></property>
</bean>
<!-- 不攔截靜態(tài)資源 -->
<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">
<!-- 調(diào)用我們配置的權(quán)限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置我們的登錄請(qǐng)求地址 -->
<property name="loginUrl" value="/login.html"/>
<!-- 配置我們?cè)诘卿涰摰卿洺晒蟮奶D(zhuǎn)地址宵距,如果你訪問的是非/login地址劝篷,則跳到您訪問的地址 -->
<property name="successUrl" value="/show"/>
<!-- 如果您請(qǐng)求的資源不再您的權(quán)限范圍,則跳轉(zhuǎn)到/403請(qǐng)求地址 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 權(quán)限配置 -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何權(quán)限即可訪問 -->
/static/**=anon
/user/login=anon
/user/registry=anon
/login=anon
<!-- perms[user:query]表示訪問此連接需要權(quán)限為user:query的用戶 -->
/user=perms[user:query]
<!-- roles[manager]表示訪問此連接需要用戶的角色為manager -->
/user/add=roles[manager]
/user/del/**=roles[admin]
/user/edit/**=roles[manager]
<!--所有的請(qǐng)求(除去配置的靜態(tài)資源請(qǐng)求或請(qǐng)求地址為anon的請(qǐng)求)都要通過登錄驗(yàn)證,如果未登錄則跳到/login-->
/** = authc
</value>
</property>
</bean>
<!--安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"></property>
</bean>
<!--登錄驗(yàn)證管理-->
<bean id="myRealm" class="com.paopao.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" ></property>
</bean>
<!--密碼加密的規(guī)則-->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5"></property>
<property name="hashIterations" value="122"></property>
</bean>
<!-- 注解權(quán)限 -->
<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實(shí)現(xiàn)認(rèn)證和權(quán)限的方法
package com.paopao.shiro;
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授權(quán)
* */
@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;
}
/**
* 認(rèn)證
* */
@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("賬號(hào)密碼錯(cuò)誤");
if (user.getState() != 1)
throw new MyException("賬號(hào)鎖定");
//加鹽散列,然后比對(duì)數(shù)據(jù)庫的密碼
String password = user.getPassword();
ByteSource salt = ByteSource.Util.bytes(user.getSalt());
AuthenticationInfo info = new SimpleAuthenticationInfo(username,password,salt, getName());
return info;
}
}
寫個(gè)登陸頁面
<!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();
}
/**
* 注冊(cè)
*/
@RequestMapping("/registry")
public ResultUtil register(@RequestParam String username,
@RequestParam String password) {
//加密
String salt = UUID.randomUUID().toString();
ByteSource sqlt =ByteSource.Util.bytes(salt);
//散列次數(shù)要和配置文件里的一樣 ==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);
/** 根據(jù)用戶名查詢用戶*/
User getByName(String username);
/** 根據(jù)用戶名查詢用戶角色*/
Set<String> getRoleByName(String username);
/** 根據(jù)用戶名查詢用戶權(quán)限*/
Set<String> getMenuByName(String username);
/** 添加用戶*/
void addUser(User user);
}
啟動(dòng)tomcat,
a.png
注冊(cè)admin,,然后登陸
b.png
權(quán)限采用注解方式,Article做測試
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleMapper articleMapper;
@RequiresPermissions("user:select") //權(quán)限
@Override
public Article getArticle(int id) {
return articleMapper.getById(id);
}
@LogAnnotation(corapation = "查詢所有")
@RequiresRoles("admin") //角色
public List<Article> getList() {
return articleMapper.getList();
}
}
訪問getlist,無法拿到數(shù)據(jù),沒有權(quán)限
c.png
實(shí)現(xiàn)注解方式的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() {
}
/**
* 注解實(shí)現(xiàn)日至切面
* 前: 獲取當(dāng)前用戶
* 后: 獲取方法的注解參數(shù)
*/
@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("執(zhí)行方法錯(cuò)誤");
}
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方法已經(jīng)加了注解.然后給admin一個(gè)admin權(quán)限,訪問加注解的方法
打印
d.png
總結(jié):
ssm基本整合
spring的注解實(shí)現(xiàn)AOP
集成shiro